Load libraries and public variables
# File that contains simulation output data in a HDF5 directory structure specified in "/publicVariables/createPublicVariables.Rmd"
simOutputH5 <- paste0("../../dataProcessing/simOutputH5Data/", experimentID, "_output.h5")
# A comprehensive table that contains all simulation input and calculated output metrics
allSimInputOutput <- read_feather("../allSimInputOutput.feather")
# This folder contains raw output files from the simulations. This is needed for calculate_para_sp_mcpsr()
rawSimOutFolder <- "/team/batch_SMOTNT/experiment1_output"
# Where figures are stored
figureBaseFolder <- "../figures/"
Validation: compare the protein synthesis rates with Weinberg 2016
weinbergData <- read_tsv("../externalData/weinberg_synthesis.txt")
Rows: 4839 Columns: 16
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (1): ORF
dbl (15): Length, RPF, mRNA, TE, IP, FEatg, FEcap, cRPF, cTE, uATG, utr, gc, pE, Ai, S
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
validationPlot <- allSimInputOutput %>%
filter(paraCombo == "mRNAconstant") %>%
select(ORF, paraCombo, MPSR, dc, r) %>%
left_join(weinbergData[, c("ORF", "S")], by = "ORF") %>%
mutate(S_perMin=S*60,
newcombo=factor(paraCombo, levels=dc.r.df$paraCombo[2:25])) %>%
ggplot(aes(x=MPSR, y=S_perMin)) +
geom_abline(linetype="dashed") +
geom_point() +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.1, label.y.npc = 0.7, size=10) +
scale_x_log10() +
scale_y_log10() +
theme_bw() +
labs(x="Mean protein synthesis rates for mRNA constant",
y="Protein synthesis rate estimates by Weinberg et al 2016")
validationPlot
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 123 rows containing non-finite values (stat_smooth).
Warning: Removed 123 rows containing non-finite values (stat_cor).
Warning: Removed 123 rows containing missing values (geom_point).

write_rds(validationPlot, "../figures/validationPlot.rds")
tmp <- allSimInputOutput %>%
filter(paraCombo == "mRNAconstant") %>%
select(ORF, paraCombo, MPSR) %>%
left_join(weinbergData[, c("ORF", "S")], by = "ORF") %>%
mutate(S_perMin=S*60)
# quick try of piping the t test didn't work..
t.test(tmp$S_perMin, tmp$MPSR, paired = TRUE)
Paired t-test
data: tmp$S_perMin and tmp$MPSR
t = 2.7885, df = 4715, p-value = 0.005317
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
0.7112053 4.0789951
sample estimates:
mean of the differences
2.3951
figS0_a <- allSimInputOutput %>%
filter(paraCombo=="mRNAconstant"|paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
ggplot(aes(x=MPSR, y=PMPSR, color = paraCombo)) +
geom_point(size = 0.5) +
geom_abline(linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Mean of protein synthesis rate'~(min^-1),
y = 'Predicted mean of protein synthesis rate'~(min^-1)) +
scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10() +
scale_y_log10()
figS0_a
`geom_smooth()` using formula 'y ~ x'

write_rds(figS0_a,"../figures/figS0_a.rds")
######################################################
figS0_b <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, MVPS, PMPSR, mRNASynRateTotal_sec) %>%
mutate(mRNASynRateTotal_min = mRNASynRateTotal_sec*60,
additiveVar = PMPSR + mRNASynRateTotal_min,
multiplicativeVar = PMPSR * mRNASynRateTotal_min + PMPSR^2*mRNASynRateTotal_min + PMPSR*mRNASynRateTotal_min^2) %>%
select(ORF, MVPS, additiveVar, multiplicativeVar) %>%
pivot_longer(names_to = "predictedVar", values_to = "predictedVarValue", cols = -c(ORF,MVPS)) %>%
ggplot(aes(x=MVPS, y=predictedVarValue, color = predictedVar)) +
geom_point(size = 0.5) +
geom_abline(linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Variance of protein synthesis rate'~(min^-1),
y = 'Predicted variance of protein synthesis rate'~(min^-1)) +
scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10() +
scale_y_log10()
figS0_b
Warning: Transformation introduced infinite values in continuous y-axis
Warning: Transformation introduced infinite values in continuous y-axis
Warning: Transformation introduced infinite values in continuous y-axis
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 31 rows containing non-finite values (stat_smooth).
Warning: Removed 31 rows containing non-finite values (stat_cor).

write_rds(figS0_b, "../figures/figS0_b.rds")
######################################################
figS0_c <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, MPSR, RMPSR) %>%
ggplot(aes(x = MPSR, y = RMPSR)) +
geom_point(size = 0.5) +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'mean prot syn rate for mRNAvarying'~(min^-1),
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10()
figS0_c
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

write_rds(figS0_c, "../figures/figS0_c.rds")
######################################################
figS0_d <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, MPSR, RMPSR) %>%
arrange(MPSR) %>%
# mutate(binNames = c(unlist(lapply(1:19, function(x){rep(x,254)})), rep(20,12))) %>% # bin all 4838 genes into 20 bins, each contains same number of genes ordered by their MPSR
# ggplot(aes(x = factor(binNames, levels = 1:20), y = RMPSR)) +
mutate(binNames = c(unlist(lapply(1:9, function(x){rep(x,537)})), rep(10,5))) %>% # bin all 4838 genes into 10 bins, each contains same number of genes ordered by their MPSR
ggplot(aes(x = factor(binNames, levels = 1:10), y = RMPSR)) +
geom_boxplot() +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'mean prot syn rate for mRNAvarying'~(min^-1),
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5)
figS0_d
`geom_smooth()` using method = 'loess' and formula 'y ~ x'

write_rds(figS0_d, "../figures/figS0_d.rds")
######################################################
figS0_e <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, MPSR, RMPSR) %>%
arrange(MPSR) %>%
# mutate(binNames = c(unlist(lapply(1:19, function(x){rep(x,254)})), rep(20,12))) %>% # bin all 4838 genes into 20 bins, each contains same number of genes ordered by their MPSR
# ggplot(aes(x = factor(binNames, levels = 1:20), y = RMPSR)) +
mutate(binNames = c(unlist(lapply(1:9, function(x){rep(x,537)})), rep(10,5))) %>% # bin all 4838 genes into 10 bins, each contains same number of genes ordered by their MPSR
group_by(binNames) %>%
mutate(test = RMPSR>1) %>%
#mutate(freqRMPSRabove1 = sum(test)/n()) %>%
summarize(freqRMPSRabove1 = sum(test)/n()) %>%
ggplot(aes(x = factor(binNames, levels = 1:10), y = freqRMPSRabove1)) +
geom_bar(stat='identity') +
#geom_abline(linetype="dashed") +
#geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'bins of genes',
y = 'freq of rel. mean prot syn rate above 1 in each bin')
figS0_e

write_rds(figS0_e, "../figures/figS0_e.rds")
######################################################
figS0_f <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, mRNAabundance, RMPSR) %>%
ggplot(aes(x = mRNAabundance, y = RMPSR)) +
geom_point(size = 0.5) +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'mRNA abundances',
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10()
figS0_f
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

write_rds(figS0_f, "../figures/figS0_f.rds")
######################################################
figS0_g <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, CAI, RMPSR) %>%
ggplot(aes(x = CAI, y = RMPSR)) +
geom_point(size = 0.5) +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'CAI',
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5)
figS0_g
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

write_rds(figS0_g, "../figures/figS0_g.rds")
######################################################
figS0_h <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, iniProb, RMPSR) %>%
ggplot(aes(x = iniProb, y = RMPSR)) +
geom_point(size = 0.5) +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'translation initiation probability',
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10()
figS0_h
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

write_rds(figS0_h, "../figures/figS0_h.rds")
######################################################
figS0_i <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
#mutate(intCtrlOrNot = ifelse(mRNADecRateNeymotin_sec==0,"intCtrl","nonCtrl")) %>%
#select(paraCombo, ORF, geneLength_codon, RMPSR, intCtrlOrNot) %>%
select(paraCombo, ORF, geneLength_codon, RMPSR) %>%
#ggplot(aes(x = geneLength_codon, y = RMPSR, color = intCtrlOrNot)) +
ggplot(aes(x = geneLength_codon, y = RMPSR)) +
geom_point(size = 0.5) +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'gene length (codon)',
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10()
figS0_i
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

write_rds(figS0_i, "../figures/figS0_i.rds")
######################################################
figS0_j <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A") %>%
select(paraCombo, ORF, mRNADecRateNeymotin_min, RMPSR) %>%
ggplot(aes(x = mRNADecRateNeymotin_min, y = RMPSR)) +
geom_point(size = 0.5) +
#geom_abline(linetype="dashed") +
geom_hline(yintercept = 1, linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "top",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'mRNA decay rates from Neymotin data (min)',
y = 'relative mean prot syn rate for mRNAvarying'~(min^-1)) +
#scale_color_manual(name="", labels=c("mRNAconstant"="mRNAconstant", "dc_1_r_0"="mRNAvarying"), values = c("#1F78B4", "#FF7F00")) +
geom_smooth() +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size=5) +
scale_x_log10()
figS0_j
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
Warning: Removed 31 rows containing non-finite values (stat_smooth).
Warning: Removed 31 rows containing non-finite values (stat_cor).

write_rds(figS0_j, "../figures/figS0_j.rds")
######################################################
figS0_k <- allSimInputOutput %>%
filter(paraCombo!= "mRNAconstant") %>%
select(dc, r, RMFR) %>%
unique() %>%
ggplot(aes(x = dc, y = RMFR, color = factor(r))) +
geom_point() +
geom_line() +
# theme_bw() +
# theme(text = element_text(size = 13),
# legend.position = "top",
# strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
# plot.margin = margin(r = 0, unit = "pt"),
# panel.grid = element_blank()
# ) +
labs(x = 'CMD levels',
y = 'Relative mean free ribosomes') +
scale_color_discrete(name = "Ribo protection index")
figS0_k
geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

write_rds(figS0_k, "../figures/figS0_k.rds")
######################################################
figS0_l <- allSimInputOutput %>%
filter(paraCombo=="dc_0_r_1", ORF!="YER053C-A") %>% #remove the gene with the 450min HL
# filter(paraCombo=="dc_0_r_1", ORF!="YER053C-A", mRNADecRateNeymotin_sec==0) %>%
# select("ORF", "RMPSR", "RMFR") %>%
mutate(intCtrlOrNot = ifelse(mRNADecRateNeymotin_sec==0,"intCtrl","nonCtrl")) %>%
select("ORF", "RMPSR", "intCtrlOrNot") %>%
#select("ORF", "RMPSR") %>%
ggplot() +
geom_density(aes(x=RMPSR, color = intCtrlOrNot)) +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = c(0.6, 0.6),
legend.background = element_blank(),
axis.ticks.y = element_blank(),
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()) +
labs(x = "Rel. mean protein synthesis rate") +
#scale_color_manual(values = c("RMVPS"="black")) +
scale_color_manual(values = c("intCtrl"="blue", "nonCtrl"="black")) +
scale_x_log10() +
geom_vline(xintercept = 1, linetype = "dashed")
figS0_l

write_rds(figS0_l, "../figures/figS0_l.rds")
Fig S1
trial_mRNAcount <- read_feather("../../simulations/trialmRNAcountData/trial_mRNAcount.feather")
trial_mRNAcount
figureS1 <- allSimInputOutput %>%
left_join(., trial_mRNAcount[,c("paraCombo","ORF","trialRMMC")], by = c("paraCombo"="paraCombo", "ORF"="ORF")) %>%
filter(paraCombo != "mRNAconstant") %>%
select(paraCombo, RMMC, trialRMMC, dc, r) %>%
`colnames<-`(c("paraCombo", "AfterScaling", "BeforeScaling", "dc", "r")) %>%
pivot_longer(names_to = "key", values_to = "RMMCvalue", cols = 2:3) %>%
ggplot(aes(x=RMMCvalue, color=key)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("1"="100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="Co-trns 0%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(title = "Fig S1: mRNA counts when varying are laregely equal to when they are constant \nafter scaling the mRNA synthesis rates",
x="Relative mean mRNA count") +
scale_y_continuous() +
theme_bw() +
theme(text=element_text(size=13),
legend.title = element_blank(),
legend.position = "bottom")
figureS1

write_rds(figureS1, "../figures/figureS1.rds")
#ggsave(paste0(figureBaseFolder, "figures1/s_fig_1.png"), dpi=100, height = 6, width = 8)
###########################################################
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant") %>%
select(paraCombo, RMMC, dc, r) %>%
ggplot(aes(x = RMMC)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("1"="100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="Co-trns 0%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(x="Relative mean mRNA count after scaling") +
scale_y_continuous() +
theme_bw() +
theme(text=element_text(size=13),
legend.title = element_blank(),
legend.position = "none") +
geom_vline(xintercept = 1, linetype = "dashed")

###########################################################
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant") %>%
select(paraCombo, RMMC, dc, r, geneLength_codon) %>%
mutate(sORl = ifelse(geneLength_codon >=512, "long", "short")) %>%
ggplot(aes(x=RMMC, color=sORl)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("1"="100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="Co-trns 0%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(x="Relative mean mRNA count") +
scale_y_continuous() +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom",
strip.text.x = element_text(size=10),
strip.text.y = element_text(size=10))

###########################################################
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant") %>%
select(paraCombo, RMMC, dc, r, mRNADecRateNeymotin_sec) %>%
mutate(fORs = ifelse(mRNADecRateNeymotin_sec >=0.0009431628, "fast", "slow")) %>%
ggplot(aes(x=RMMC, color=fORs)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("1"="100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="Co-trns 0%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(x="Relative mean mRNA count") +
scale_y_continuous() +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom",
strip.text.x = element_text(size=10),
strip.text.y = element_text(size=10))

allSimInputOutput%>%
filter(ORF!="YER053C-A", mRNADecRateNeymotin_sec!=0, paraCombo!="mRNAconstant") %>%
mutate(dc_fct=factor(dc, levels=c("1", "0.8", "0.6", "0.4", "0.2", "0"))) %>%
ggplot(aes(x=dc_fct, y=RMMC, fill=r)) +
geom_boxplot(outlier.size = 0.1) +
# geom_hline(aes(yintercept=median(as.numeric(unlist(allSimInputOutput%>%filter(ORF!="YER053C-A", mRNADecRateNeymotin_sec!=0, paraCombo=="dc_1_r_0")%>%select(RMMDR))), na.rm = TRUE)), color="red", linetype="dashed") +
theme_bw() +
labs(x="CMD level",
y="Relative mean mRNA count") +
scale_x_discrete(labels=c("1"="100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="0")) +
scale_fill_discrete(name = "Ribosome\nprot index") +
theme(
text = element_text(size = 13),
legend.position = "none"
)

allSimInputOutput %>%
group_by(paraCombo) %>%
summarise(M = mean(RMMC)) %>%
arrange(desc(M))
allSimInputOutput %>%
group_by(dc) %>%
summarise(M = mean(RMMC)) %>%
arrange(desc(M))
NA
Fig. was S3, now S2
figureS2 <- allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", ORF != "YER053C-A", mRNADecRateNeymotin_sec != 0) %>%
ggplot(aes(x = MMC, y = MVMC)) +
geom_point(size = 0.5) +
geom_abline(linetype = "dashed") +
facet_grid(dc~r, labeller = labeller(dc = c("1" = "100%", "0.8" = "80%", "0.6" = "60%", "0.4" = "40%", "0.2" = "20%", "0" = "Co-trns 0%"), r = c("0" = "Ribo prot indx = 0", "0.1" = "0.1", "0.4" = "0.4", "1" = "1"), label_parsed)) +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "none",
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Mean of mRNA count',
y = 'Variance of mRNA count') +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.7, label.y.npc = 0.4, size = 5) +
scale_x_log10() +
scale_y_log10()
figureS2
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS2, "../figures/figureS2.rds")
was Fig S4, now S3: Sequence features correlate with the fano factor of protein synthesis rates for mRNA constant
plot_fun1 <- function(var1, var2){ allSimInputOutput%>% #var1:"MeanProteinSynRate".. var2:"mRNAconstant", "dc_1_r_0"
filter(paraCombo == var2, mRNADecRateNeymotin_sec != 0) %>%
select(ORF, MPSR, MVPS, iniProb_log10, mRNAabundance_log10, mRNADecRateNeymotin_sec_log10, CAI, geneLength_codon_log10) %>%
mutate(fano_protSyn = MVPS/MPSR) %>%
filter(fano_protSyn>0.3) %>% # filter out the two outliers
`colnames<-`(paste0("",c("ORF", "MeanProteinSynRate", "VarianceProteinSynRate", "iniProb_log10", "mRNALevel_log10", "DecRate_log10", "CAI", "geneLength_log10", "fano_protSynRate"))) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !c(ORF,MeanProteinSynRate, VarianceProteinSynRate, fano_protSynRate)) %>%
ggplot(aes_string(x = "featureVals", y = var1)) +
geom_point(size = 0.5) +
facet_wrap(~feature, scales = "free", nrow = 1, strip.position = "bottom") +
theme_bw() +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.4, label.y.npc = 0.13, size = 3) +
labs(x = "",
y = var1) +
scale_y_log10() +
theme(text = element_text(size = 13),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside" #to put the strip labels below x-axis
)
}
figureS3 <- plot_fun1("fano_protSynRate", "mRNAconstant")
figureS3
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS3, "../figures/figureS3.rds")
Was Fig S5, now S4.
# MMDP = mRNAs marked for degradation proportion among mean total mRNA
figureS4 <- allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0) %>%
ggplot(aes(x = MMDP, y = RMPSR)) +
geom_point(size = 0.1) +
scale_x_log10() +
scale_y_log10() +
labs(x = "Proportion of mRNA marked for decay",
y = "Relative mean of protein synthesis rates",
title = "") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.1, label.y.npc = 0.3, size = 3) +
theme_bw() +
theme(text=element_text(size = 13))
figureS4
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS4, "../figures/figureS4.rds")
Fig. S5
figureS5 <- allSimInputOutput %>%
filter(paraCombo=="dc_1_r_0", ORF!="YER053C-A", mRNADecRateNeymotin_sec!=0) %>%
select("ORF", "CVPS", "CVMC", "paraCombo") %>% #remove the gene with the 450min HL
ggplot(aes(x=CVMC, y=CVPS, colour=paraCombo)) +
geom_point(size = 0.5) +
geom_abline(linetype="dashed") +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "none",
strip.text = element_text(color="white"), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x ="CV for mRNA count per min",
y = "CV for protein synthesis rate") +
#scale_color_discrete(name="",labels=c("Co-trans 100% RiboProtect 0")) +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.5, label.y.npc = 0.3, size=5) +
scale_x_log10() + # not able to add the inset if i keep the log scales for either x or y
scale_y_log10() +
scale_color_manual(name="", labels=c("Co-trans 100% RiboProtect 0"), values = c("dc_1_r_0" = "black"))
figureS5
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS5, "../figures/figureS5.rds")
Fig S6: relative CV = CV of the protein synthesis rate/CV of the mRNA count
figureS6 <- allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YCR024C-B") %>% #"YCR024C-B" is an outlier whose relCV = 23
mutate(relCV = CVPS/CVMC) %>%
select(ORF, relCV, iniProb_log10, mRNAabundance_log10, mRNADecRateNeymotin_sec_log10, CAI, geneLength_codon_log10) %>%
`colnames<-`(paste0("", c("ORF", "Relative_CV", "iniProb_log10", "mRNALevel_log10", "DecRate_log10", "CAI", "geneLength_log10"))) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", -c(ORF, Relative_CV)) %>%
ggplot(aes(x = featureVals, y = Relative_CV)) +
geom_point(size = 0.5) +
facet_wrap(~feature, scales = "free", nrow = 1, strip.position = "bottom") +
theme_bw() +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.15, label.y.npc = 0.8, size = 3) +
labs(x = "",
y = "Relative CV") +
scale_y_log10() +
theme(text = element_text(size = 13),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside") #to put the strip labels below x-axis
figureS6
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS6, "../figures/figureS6.rds")
Fig. S7:
figureS7 <- allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !geneLength_codon) %>%
ggplot(aes(x = featureVals, y = geneLength_codon)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Gene length (codon)",
title = "dc_1_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
figureS7
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS7, "../figures/figureS7.rds")
###################################################
allSimInputOutput %>%
filter(paraCombo == "dc_1_r_1", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A",ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !geneLength_codon) %>%
ggplot(aes(x = featureVals, y = geneLength_codon)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Gene length (codon)",
title = "dc_1_r_1") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

tmp <- allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A",ORF != "YGR169C-A", ORF != "YLR106C",ORF != "YCR024C-B") %>%
mutate(RDR = MMDR/mRNADecRateNeymotin_sec) %>%
select(RMTE, geneLength_codon, RDR)
summary(lm(RMTE~geneLength_codon+RDR, tmp))
Call:
lm(formula = RMTE ~ geneLength_codon + RDR, data = tmp)
Residuals:
Min 1Q Median 3Q Max
-0.080870 -0.005794 0.000774 0.008152 0.075226
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.320e-01 9.835e-03 43.92 <2e-16 ***
geneLength_codon -2.947e-05 1.010e-06 -29.18 <2e-16 ***
RDR 6.010e-01 9.869e-03 60.90 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.01439 on 4801 degrees of freedom
Multiple R-squared: 0.8319, Adjusted R-squared: 0.8319
F-statistic: 1.188e+04 on 2 and 4801 DF, p-value: < 2.2e-16
# MMDP = mRNAs marked for degradation proportion among mean total mRNA
# MTT = mean translation time
allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0) %>%
ggplot(aes(x = MTT, y = MMDP)) +
geom_point(size = 0.1) +
scale_x_log10() +
scale_y_log10() +
labs(x = "Mean translation time",
y = "Proportion of mRNA marked for decay",
title = "") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.1, label.y.npc = 0.3, size = 3) +
theme_bw()
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0.2_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !geneLength_codon) %>%
ggplot(aes(x = featureVals, y = geneLength_codon)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Gene length (codon)",
title = "dc_0.2_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0.2_r_1", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !geneLength_codon) %>%
ggplot(aes(x = featureVals, y = geneLength_codon)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Gene length (codon)",
title = "dc_0.2_r_1") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 1 rows containing non-finite values (stat_smooth).
Warning: Removed 1 rows containing non-finite values (stat_cor).

Fig. S8
figureS8 <- allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_1_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
figureS8
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS8, "../figures/figureS8.rds")
#############################################
allSimInputOutput %>%
filter(paraCombo == "dc_0.8_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_0.8_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0.6_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_0.6_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0.4_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1,strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_0.4_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0.2_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_0.2_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_0_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color="black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 4804 rows containing non-finite values (stat_smooth).
Warning: Removed 4804 rows containing non-finite values (stat_cor).

allSimInputOutput %>%
filter(paraCombo == "dc_1_r_1", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_1_r_1") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text=element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

allSimInputOutput %>%
filter(paraCombo == "dc_0.2_r_1", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
`colnames<-` (c("RelMeanTE", "MeanTransTime", "mRNAMarkdDecProp", "geneLength_codon", "RelativeDecRate")) %>%
pivot_longer(names_to = "feature", values_to = "featureVals", !RelMeanTE) %>%
ggplot(aes(x = featureVals, y = RelMeanTE)) +
geom_point(size = 0.1) +
facet_wrap(~feature, scales = "free_x", nrow = 1, strip.position = "bottom") +
scale_x_log10() +
scale_y_log10() +
labs(x = "",
y = "Relative mean TE",
title = "dc_0.2_r_1") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 1 rows containing non-finite values (stat_smooth).
Warning: Removed 1 rows containing non-finite values (stat_cor).

allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(MMDP, RMMDR) %>%
ggplot(aes(x = MMDP, y = RMMDR)) +
geom_point(size = 0.1) +
labs(x = "MMDP",
y = "Relative decay rates",
title = "dc_1_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

# MMDP = mRNAs marked for degradation proportion
allSimInputOutput %>%
filter(paraCombo == "dc_0.2_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
select(MMDP, RMMDR) %>%
ggplot(aes(x = MMDP, y = RMMDR)) +
geom_point(size = 0.1) +
scale_x_log10() +
scale_y_log10() +
labs(x = "MMDP",
y = "Relative decay rates",
title = "dc_0.2_r_0") +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.3, label.y.npc = 0.1, size = 3) +
theme_bw() +
theme(text = element_text(size = 13),
axis.text.x = element_text(size = rel(0.8)),
strip.text = element_text(color = "black"), # can't use element_blank() here because it gives error when p1+p2
strip.background = element_blank(),
strip.placement = "outside")
`geom_smooth()` using formula 'y ~ x'

Fig. S9
figureS9 <- allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B", dc != 0) %>%
#select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
ggplot(aes(x = MMDP, y = RMTE)) +
geom_point(size = 0.1) +
facet_grid(dc~r, labeller = labeller(dc = c("1" = "100%", "0.8" = "80%", "0.6" = "60%", "0.4" = "40%", "0.2" = "Co-trns 20%"), r = c("0" = "Ribo prot indx = 0", "0.1" = "0.1", "0.4" = "0.4", "1" = "1"), label_parsed)) +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "none",
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Proportions of mRNAs undergoing CMD for all genes',
y = 'Relative mean translation efficiencies') +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.2, label.y.npc = 0.4, size = 5) +
scale_x_log10() +
scale_y_log10()
figureS9
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 1 rows containing non-finite values (stat_smooth).
Warning: Removed 1 rows containing non-finite values (stat_cor).

write_rds(figureS9, "../figures/figureS9.rds")
##############################################################
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B", , r==0|r==1, dc==0.2|dc==1) %>%
#select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
ggplot(aes(x = MMDP, y = RMTE)) +
geom_point(size = 0.1) +
facet_grid(dc~r, labeller = labeller(dc = c("1" = "100%", "0.8" = "80%", "0.6" = "60%", "0.4" = "40%", "0.2" = "Co-trns 20%"), r = c("0" = "Ribo prot indx = 0", "0.1" = "0.1", "0.4" = "0.4", "1" = "1"), label_parsed)) +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "none",
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Proportions of mRNAs undergoing CMD for all genes',
y = 'Relative mean translation efficiencies') +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.2, label.y.npc = 0.4, size = 5) +
scale_x_log10() +
scale_y_log10()
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
Warning: Transformation introduced infinite values in continuous x-axis
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 1 rows containing non-finite values (stat_smooth).
Warning: Removed 1 rows containing non-finite values (stat_cor).

Fig. S10
figureS10 <- allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B") %>%
#select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
ggplot(aes(x = RMMDR, y = RMTE)) +
geom_point(size = 0.1) +
facet_grid(dc~r, labeller = labeller(dc = c("1" = "100%", "0.8" = "80%", "0.6" = "60%", "0.4" = "40%", "0.2" = "20%", "0" = "Co-trns 0%"), r = c("0" = "Ribo prot indx = 0", "0.1" = "0.1", "0.4" = "0.4", "1" = "1"), label_parsed)) +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "none",
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Relative mRNA decay rates',
y = 'Relative mean translation efficiencies') +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.2, label.y.npc = 0.4, size = 5) +
scale_x_log10() +
scale_y_log10()
figureS10
`geom_smooth()` using formula 'y ~ x'

write_rds(figureS10, "../figures/figureS10.rds")
#########################################################
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", ORF != "YGR169C-A", ORF != "YLR106C", ORF != "YCR024C-B", r==0|r==1, dc==0|dc==1) %>%
#select(RMTE, MTT, MMDP, geneLength_codon, RMMDR) %>%
ggplot(aes(x = RMMDR, y = RMTE)) +
geom_point(size = 0.1) +
facet_grid(dc~r, labeller = labeller(dc = c("1" = "100%", "0.8" = "80%", "0.6" = "60%", "0.4" = "40%", "0.2" = "20%", "0" = "Co-trns 0%"), r = c("0" = "Ribo prot indx = 0", "0.1" = "0.1", "0.4" = "0.4", "1" = "1"), label_parsed)) +
theme_bw() +
theme(text = element_text(size = 13),
legend.position = "none",
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank()
) +
labs(x = 'Relative mRNA decay rates',
y = 'Relative mean translation efficiencies') +
geom_smooth(method = "lm") +
stat_cor(aes(label = paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.2, label.y.npc = 0.4, size = 5) +
scale_x_log10() +
scale_y_log10()
`geom_smooth()` using formula 'y ~ x'

was Fig. S9, maybe should not use it coz the vline calculated from its input decay rate may not be accurate.
lifetimeDistri<- function(genevec){
dfplot <- cbind(dc.r.df[c(2:5, 22:25), ], data.frame(matrix(NA, ncol = 5000, nrow = 8*3))) %>%
mutate(ORF = c(rep(genevec[1], 8), rep(genevec[2], 8), rep(genevec[3], 8))) %>%
relocate(ORF)
for(i in 1:8){dfplot[i, 6:5005] = as.vector(h5read(simOutputH5, paste0(genevec[1], "/mRNA_lifeTimes/", dfplot$paraCombo[i])))}
for(i in 9:16){dfplot[i, 6:5005] = as.vector(h5read(simOutputH5, paste0(genevec[2], "/mRNA_lifeTimes/", dfplot$paraCombo[i])))}
for(i in 17:24){dfplot[i, 6:5005] = as.vector(h5read(simOutputH5, paste0(genevec[3], "/mRNA_lifeTimes/", dfplot$paraCombo[i])))}
dfplot %>%
pivot_longer(names_to = "varyingParaCombo", values_to = "lifeTimes", cols = 6:5005) %>%
ggplot(aes(lifeTimes, fill = dc)) +
geom_density(alpha = 0.5, color = NA) +
facet_grid(factor(ORF, levels = genevec)~r,
labeller = labeller(r = c("0" = "Ribo prot index 0", "0.1" = "0.1", "0.4" = "0.4", "1" = "1"))) +
scale_x_log10(labels = scales::comma_format(accuracy = 1L)) +
scale_fill_discrete(name = "CMD level",
labels = c("0" = "0", "0.2" = "20%", "0.6" = "60%", "1" = "100%")) +
theme_bw() +
labs(x = paste0("mRNA life time distribution (log10)")) +
theme(
legend.position = "top",
legend.justification = "left",
text = element_text(size = 13),
axis.text.x = element_text(size = 8)) +
geom_vline(data = filter(dfplot, ORF == genevec[1]), aes(xintercept = 1/simInputFeatures$mRNADecRateNeymotin_sec[which(simInputFeatures$ORF == genevec[1])]), linetype = "dashed", color = "dark grey") + #1049.856 =1/simInputFeatures$mRNADecRateNeymotin_sec[1] # 1049.856 is the input lifetime for YAL001C
geom_vline(data = filter(dfplot, ORF == genevec[2]), aes(xintercept = 1/simInputFeatures$mRNADecRateNeymotin_sec[which(simInputFeatures$ORF == genevec[2])]), linetype = "dashed", color = "dark grey") +
geom_vline(data = filter(dfplot, ORF == genevec[3]), aes(xintercept = 1/simInputFeatures$mRNADecRateNeymotin_sec[which(simInputFeatures$ORF == genevec[3])]), linetype = "dashed", color = "dark grey")
# the above lines are the average life time calculated from input decay rates
}
lifetimeDistri(c("YAL001C", "YKR075C", "YBR011C"))

lifetimeDistri(c("YLR106C", "YKR054C", "YHR099W")) # longest genes
Warning: Removed 6188 rows containing non-finite values (stat_density).

lifetimeDistri(c("YAR002C-A", "YBL050W", "YBR003W"))

allSimInputOutput %>%
filter(paraCombo == "dc_0_r_0", mRNADecRateNeymotin_sec != 0, mRNAabundance>1, ORF!="YER053C-A", ORF!="YLR106C") %>% #remove the gene with HL=450min, also an outlier gene "YLR106C" with RMTE==0.6
select(ORF, paraCombo, RMTE, mRNAabundance_log10, iniProb_log10, mRNADecRateNeymotin_sec_log10, CAI, geneLength_codon_log10) %>%
`colnames<-`(c("ORF", "paraCombo", "RMTE", "log(mRNAabundance)", "log(IniProb)", "log(DecRate)", "CAI", "log(Length)")) %>%
pivot_longer(cols = -c(RMTE, paraCombo, ORF), names_to = "feature", values_to = "featureVal") %>%
ggplot(aes(x=featureVal, y=RMTE, color=paraCombo)) +
geom_point(size=0.5) +
facet_wrap(~feature, scales = "free", nrow=1, strip.position = "bottom") +
theme_bw() +
scale_y_log10() +
theme(text = element_text(size = 13),
legend.position = "none",
strip.text = element_text(color="black", size=rel(1.2)), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank(),
strip.background = element_blank(),
strip.placement = "outside" #to put the strip labels below x-axis
) +
labs(x = "",
y = "Relative mean translation efficiency",
title = "dc_0_r_0") +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.3, label.y.npc = 0.2, size=5) +
scale_color_manual(name="", labels=c(""), values = c("dc_1_r_0" = "#1F78B4"))
allSimInputOutput %>%
filter(paraCombo == "dc_0_r_1", mRNADecRateNeymotin_sec != 0, mRNAabundance>1, ORF!="YER053C-A", ORF!="YLR106C") %>% #remove the gene with HL=450min, also an outlier gene "YLR106C" with RMTE==0.6
select(ORF, paraCombo, RMTE, mRNAabundance_log10, iniProb_log10, mRNADecRateNeymotin_sec_log10, CAI, geneLength_codon_log10) %>%
`colnames<-`(c("ORF", "paraCombo", "RMTE", "log(mRNAabundance)", "log(IniProb)", "log(DecRate)", "CAI", "log(Length)")) %>%
pivot_longer(cols = -c(RMTE, paraCombo, ORF), names_to = "feature", values_to = "featureVal") %>%
ggplot(aes(x=featureVal, y=RMTE, color=paraCombo)) +
geom_point(size=0.5) +
facet_wrap(~feature, scales = "free", nrow=1, strip.position = "bottom") +
theme_bw() +
scale_y_log10() +
theme(text = element_text(size = 13),
legend.position = "none",
strip.text = element_text(color="black", size=rel(1.2)), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank(),
strip.background = element_blank(),
strip.placement = "outside" #to put the strip labels below x-axis
) +
labs(x = "",
y = "Relative mean translation efficiency",
title = "dc_0_r_1") +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.3, label.y.npc = 0.2, size=5) +
scale_color_manual(name="", labels=c(""), values = c("dc_1_r_0" = "#1F78B4"))
allSimInputOutput %>%
filter(paraCombo == "dc_1_r_1", mRNADecRateNeymotin_sec != 0, mRNAabundance>1, ORF!="YER053C-A", ORF!="YLR106C") %>% #remove the gene with HL=450min, also an outlier gene "YLR106C" with RMTE==0.6
select(ORF, paraCombo, RMTE, mRNAabundance_log10, iniProb_log10, mRNADecRateNeymotin_sec_log10, CAI, geneLength_codon_log10) %>%
`colnames<-`(c("ORF", "paraCombo", "RMTE", "log(mRNAabundance)", "log(IniProb)", "log(DecRate)", "CAI", "log(Length)")) %>%
pivot_longer(cols = -c(RMTE, paraCombo, ORF), names_to = "feature", values_to = "featureVal") %>%
ggplot(aes(x=featureVal, y=RMTE, color=paraCombo)) +
geom_point(size=0.5) +
facet_wrap(~feature, scales = "free", nrow=1, strip.position = "bottom") +
theme_bw() +
scale_y_log10() +
theme(text = element_text(size = 13),
legend.position = "none",
strip.text = element_text(color="black", size=rel(1.2)), # can't use element_blank() here because it gives error when p1+p2
plot.margin = margin(r = 0, unit = "pt"),
panel.grid = element_blank(),
strip.background = element_blank(),
strip.placement = "outside" #to put the strip labels below x-axis
) +
labs(x = "",
y = "Relative mean translation efficiency",
title = "dc_1_r_1") +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`,`~")), label.x.npc = 0.3, label.y.npc = 0.2, size=5) +
scale_color_manual(name="", labels=c(""), values = c("dc_1_r_0" = "#1F78B4"))
tmpdf <- data.frame(lifetime = log10(as.numeric(dfplot[1, 6:5005])))
which.max(density(tmpdf$lifetime)$y)
density(tmpdf$lifetime)$x[387]
ggplot(tmpdf, aes(lifetime)) + geom_density() + geom_vline(xintercept = density(tmpdf$lifetime)$x[387])
Fig. S
NOTES: Output decay rate = 1/mean lifetime https://en.wikipedia.org/wiki/Particle_decay
Total output decay rate = output decay rate * output mean mRNA count
Total input decay rate = input decay rate * mRNAabundance
Total synthesis rate = a scaled constant
(The above rates are all gene-specific)
Summary: changing total output decay rate is a result of changing co-translational decay and ribosome protection. In order to maintain the constant mRNA level, we have to scale the total synthesis rates to counter-effect the changing output decay rates.
When co-translational decay is higher than 0, there’s always a surplus of mRNAs marked for decay, that are not accounted when calculating total decay probabilities (They’re not accounted because they already have decay machinery bound to them, so cannot be accounted again into the mRNA pool that can still be degraded). Therefore the synthesis rates are scaled, in order to maintain a stable relative mRNA count (= mean output mRNA count/mRNAabundance) for it to be close to 1 (Supp Fig 1). The mean output mRNA count for each gene is a result of the balance between its scaled synthesis rate and total output decay rate. In other words, the total output decay rate directly respond to the scaled synthesis rate, rather than the input decay rate.
The scaled total synthesis rates are the smallest when co-translational decay = 100%, so that the total real-time mRNA count can be close to mRNAabundance even with the highest amount of mRNAs marked for decay. In contrast, the scaled total synthesis rates are the largest and equal to the total input decay rates when co-trans decay = 0% (Supp Fig 2a), because there is 0 mRNA marked for decay.
Hypothetically, the total output decay rates should equal to the total synthesis rates in order to maintain the real-time mRNA count to be largely the same at the beginning and the end of the simulation. If unequal, the real-time mRNA count should either go up or down as the simulation continues compared to the begining amount (i.e. mRNAabundance). However, our results show that the total output decay rates are slightly larger than the scaled synthesis rates across all the parameter combos (Supp Fig 2b. this is the part I don’t understand, is it coz the total output decay rates include considering mRNAsMarkedForDecay, but the total scaled synthesis rates doesn’t include mRNAsMarkedForDecay), and that’s somehow contributing to the mean real-time mRNA count being equal to mRNAabundance as shown in Supp Fig 1.
Because the output decay rates directly respond to total synthesis rates, they are influenced by the para combos in the same way that total synthesis rates are. That explains why Supp Fig 2c is similar to Supp Fig 2a in that the peaks skew to the right as co-translational decay ratio goes down. However in Supp Fig 2a, the ratio (scaled synthesis rates V.S. total input decay rates) skewed from less than 1 to 1; while in Supp Fig 2c, the ratio (total output decay rates V.S. total input decay rates) skewed from 1 to larger than 1. This would make sense if we can explain what’s going on in Supp Fig 2b.
Meanwhile, the output decay rates for short genes are much less affected by different co-translational decay proportions than long genes (Supp Fig 2d). This should be a reflection that the total synthesis rates for short genes are changing less with changing co-translational decay.
Supp Fig 2a: The scaled synthesis rates are the smallest when co-trans decay = 100%, while theythe largest and equal to the total input decay rates when co-trans decay = 0%
Supp Fig 2b: Total output mRNA decay rates are slightly larger than scaled mRNA synthesis rates , but the ratio stays stable with changing parameters (I don’t understand why the decay rates have to be larger)
Supp Fig 2c: Output decay rates respond to scaled synthesis rates, therefore its ratio against input decay rates shows similar patter as scaled synthesis rates in Fig 2
Supp Fig 2d: Output decay rates for short genes are much less affected by different -translational decay than long genes
allSimInputOutput_trial <- read_feather("../../../exp0/externalData/exp11_outcomeAll.feather")
tmp <- allSimInputOutput_trial %>%
filter(combo != "mRNAconstant", w != 0.01, w != 0.05, w != 0.2) %>%
select(NMMC, combo, ORF, r, w) %>% # NMMC in trial = RMMC in exp0, "normalized" VS "relative"
mutate(dc=1-as.numeric(r)) %>%
select(-r) %>% #delete the original column named "r", in trial data the r means CMD levels, and w means ribosome protection index
dplyr::rename("r"="w", "paraCombo"="combo", "RMMCtrial"="NMMC") %>% # change the original col named "w" into "r", b/c "r" in exp0 means ribosome protection index
mutate(paraCombo=paste0("dc_", dc, "_r_", r)) %>%
select(-dc, -r)
sup1 <- (allSimInputOutput %>%
filter(paraCombo != "mRNAconstant") %>%
left_join(., tmp, by = c("paraCombo"="paraCombo", "ORF"="ORF"))) %>%
select("paraCombo", "RMMC", "RMMCtrial", "dc", "r") %>%
dplyr::rename("AfterScaling"="RMMC", "BeforeScaling"="RMMCtrial") %>%
pivot_longer(names_to = "key", values_to = "RMMCvalue", cols = 2:3) %>%
ggplot(aes(x=RMMCvalue, color=key)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("0"="0%", "0.2"="20%", "0.4"="40%", "0.6"="60%", "0.8"="80%", "1"="CMD 100%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(title = "Sup Fig 1: mRNA counts when varying are laregely equal to when they are constant \nafter scaling the mRNA synthesis rates",
x="Relative mean mRNA count") +
scale_y_continuous() +
geom_vline(xintercept =1, linetype="dashed", color="dark grey") +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom",
strip.text.x = element_text(size=10),
strip.text.y = element_text(size=10)) # make the gridline color darker
############################################ plotting the (total syn rate after scaling)/(input decay rate*mRNAabundance) for all genes for all rw combos
outdf <- tibble(matrix(NA, ncol=nrow(dc.r.df)-1, nrow=4839))
for (i in 1:(nrow(dc.r.df)-1))
{
inf <- read.table(paste0("../../simulations/simInput/allGenesDecrEqualsSynrWithScaling_", dc.r.df$paraCombo[i+1], "_S.cer.mRNA.ini.abndc.syn.dec.tsv"))
outdf[, i] <- inf[, 3]/(inf[, 4]*inf[, 2])
}
colnames(outdf) <- dc.r.df$paraCombo[2:nrow(dc.r.df)]
sup2a <- outdf %>%
pivot_longer(names_to = "paraCombo", values_to = "value", cols = 1:(nrow(dc.r.df)-1)) %>%
left_join(., dc.r.df, by = "paraCombo") %>%
filter(value != 0, paraCombo == "dc_1_r_0"|paraCombo == "dc_0_r_0"|paraCombo == "dc_1_r_1"|paraCombo == "dc_0_r_1") %>%
ggplot(aes(x=value)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("0"="0%", "0.2"="20%", "0.4"="40%", "0.6"="60%", "0.8"="80%", "1"="CMD 100%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
geom_vline(xintercept =1, linetype="dashed", color="dark grey") +
labs(title = "",
x="Scaled synthesis rates/Total input decay rates") +
theme_bw() +
theme(strip.text.x = element_text(size=9),
strip.text.y = element_blank()) +
scale_x_continuous(breaks = c(0.9, 1, 1.1, 1.3, 1.5))
############################################## plotting the (output decay rate)/(syn rate after scaling) for all genes for all dc/r paraCombos
mmdrAllgeneAlldcr <- read_feather("../calculatedMetrics/mmdrAllgeneAlldcr.feather")[, 2:nrow(dc.r.df)]
mmcAllgeneAlldcr<- read_feather("../calculatedMetrics/mmcAllgeneAlldcr.feather")[, 2:nrow(dc.r.df)]
totdr <- mmdrAllgeneAlldcr*mmcAllgeneAlldcr
totsynr <- tibble(matrix(NA, ncol=nrow(dc.r.df)-1, nrow=4839))
for (i in 1:(nrow(dc.r.df)-1))
{
inf <- read.table(paste0("../../simulations/simInput/allGenesDecrEqualsSynrWithScaling_", dc.r.df$paraCombo[i+1], "_S.cer.mRNA.ini.abndc.syn.dec.tsv"))
totsynr[, i] <- inf[, 3]
}
ratio.dr.synr <- totdr/totsynr
colnames(ratio.dr.synr) <- dc.r.df$paraCombo[2:nrow(dc.r.df)]
ratio.dr.synr <- ratio.dr.synr[-1278, ] # gene with the HL-min=490 min, the data point skews the scale
sup2b <- ratio.dr.synr %>%
pivot_longer(names_to = "paraCombo", values_to = "value", cols = 1:(nrow(dc.r.df)-1)) %>%
left_join(., dc.r.df, by = "paraCombo") %>%
filter(paraCombo == "dc_1_r_0"|paraCombo == "dc_0_r_0"|paraCombo == "dc_1_r_1"|paraCombo == "dc_0_r_1") %>%
filter(!is.na(value)) %>%
ggplot(aes(x=value)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("0"="0%", "0.2"="20%", "0.4"="40%", "0.6"="60%", "0.8"="80%", "1"="CMD 100%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(title = "",
x="Total output decay rates/Scaled synthesis rates") +
geom_vline(xintercept =1, linetype="dashed", color="dark grey") +
theme_bw() +
theme(strip.text.x = element_text(size=9),
strip.text.y = element_text(size=9),
axis.title.y = element_blank())
############################################ plotting the (output decay rate*real time mRNA)/(input decay rate*mRNAabundance)for all genes for all rw combos
outdf <- tibble(matrix(NA, ncol=nrow(dc.r.df)-1, nrow=4839)) #contains all the total input decay rates
for (i in 1:(nrow(dc.r.df)-1)) # these 16 columns are all the same, all equal to simInputFeatures$mRNAabundance*simInputFeatures$mRNADecRateNeymotin_sec
{
inf <- read.table(paste0("../../simulations/simInput/allGenesDecrEqualsSynrWithScaling_", dc.r.df$paraCombo[i+1], "_S.cer.mRNA.ini.abndc.syn.dec.tsv"))
outdf[, i] <- (inf[, 4]*inf[, 2])
}
outdf <- totdr/outdf
colnames(outdf) <- dc.r.df$paraCombo[2:nrow(dc.r.df)]
sup2c <- outdf[-1278, ] %>% # gene with the HL-min=490 min, the data point skews the scales
pivot_longer(names_to = "paraCombo", values_to = "value", cols = 1:(nrow(dc.r.df)-1)) %>%
left_join(., dc.r.df, by = "paraCombo") %>%
filter(value != 0, paraCombo == "dc_1_r_0"|paraCombo == "dc_0_r_0"|paraCombo == "dc_1_r_1"|paraCombo == "dc_0_r_1") %>%
ggplot(aes(x=value)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("0"="0%", "0.2"="20%", "0.4"="40%", "0.6"="60%", "0.8"="80%", "1"="CMD 100%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
geom_vline(xintercept =1, linetype="dashed", color="dark grey") +
labs(title = "",
x="Total output decay rates/Total input decay rates") +
theme_bw() +
theme(#strip.text.x = element_text(size=8),
strip.text.y = element_blank(),
strip.text.x = element_blank()) # hide the grid title
############################################
# sl = short or long
outdf$sl <- rep(NA,4839)
outdf$sl[which(simInputFeatures$geneLength_codon>512)] <- "Long"
outdf$sl[which(simInputFeatures$geneLength_codon<=512)] <- "Short"
sup2d <- outdf[-1278, ] %>% # took the gene with the HL-min=490 min, the data point skews the scales
pivot_longer(names_to = "paraCombo", values_to = "value", cols = 1:(nrow(dc.r.df)-1)) %>%
left_join(., dc.r.df, by = "paraCombo") %>%
filter(value != 0, paraCombo == "dc_1_r_0"|paraCombo == "dc_0_r_0"|paraCombo == "dc_1_r_1"|paraCombo == "dc_0_r_1") %>%
ggplot(aes(x=value, color=sl, group=sl)) +
geom_density() +
facet_grid(dc~r, labeller=labeller(dc=c("0"="0%", "0.2"="20%", "0.4"="40%", "0.6"="60%", "0.8"="80%", "1"="CMD 100%"), r=c("0"="Ribo prot indx = 0", "0.1"="0.1", "0.4"="0.4", "1"="1"), label_parsed)) +
labs(title = "",
x="Total output decay rates/Total input decay rates") +
geom_vline(xintercept =1, linetype="dashed", color="dark grey") +
theme_bw() +
theme(
strip.text.y = element_text(size=9),
strip.text.x = element_blank(),
legend.position = c(0.9, 0.95),
axis.title.y = element_blank(),
legend.background=element_blank(), # change the legend background to transparent
legend.key.size = unit(0.5, "line")) +
scale_color_discrete(name = "", labels = )
############################################
sup1
sup2 <- (sup2a|sup2b)/(sup2c|sup2d)
sup2 + plot_annotation(
title = 'Supp Fig 2.',
# subtitle = 'Supp Fig 2.',
# caption = 'Hello', # this one appears at the bottom
tag_levels = 'a'
)
####################################
tot.in.dr <- tibble(matrix(NA, ncol=nrow(dc.r.df)-1, nrow=4839)) #contains all the total input decay rates
for (i in 1:(nrow(dc.r.df)-1)) # these 16 columns are all the same, all equal to simInputFeatures$mRNAabundance*simInputFeatures$mRNADecRateNeymotin_sec
{
inf <- read.table(paste0(basefolder, expID, "/input/allGenesDecrEqualsSynrWithScaling_", dc.r.df$paraCombo[i+1], "_S.cer.mRNA.ini.abndc.syn.dec"))
tot.in.dr[, i] <- (inf[, 4]*inf[, 2])
}
mmdrAllgeneAlldcr <- read_feather(paste0(basefolder, expID, "/analyses/featherFiles/mmdrAllgeneAlldcr.feather"))[, 2:nrow(dc.r.df)]
mmcAllgeneAlldcr<- read_feather(paste0(basefolder, expID, "/analyses/featherFiles/mmcAllgeneAlldcr.feather"))[, 2:nrow(dc.r.df)]
tot.out.dr <- mmdrAllgeneAlldcr*mmcAllgeneAlldcr
outdf <- tot.out.dr/tot.in.dr
colnames(outdf) <- dc.r.df$paraCombo[2:nrow(dc.r.df)]
outdf[-1278, ] %>% # gene with the HL-min=490 min, the data point skews the scales
pivot_longer(names_to = "paraCombo", values_to = "outInDrRatio", cols = 1:(nrow(dc.r.df)-1)) %>%
left_join(., dc.r.df, by = "paraCombo") %>%
filter(outInDrRatio != 0) %>%
mutate(dc_fct=factor(dc, levels=c("1", "0.8", "0.6", "0.4", "0.2", "0"))) %>%
ggplot(aes(x=dc_fct, y=outInDrRatio, fill=r)) +
geom_boxplot(outlier.size = 0.1) +
geom_hline(aes(yintercept=median(as.numeric(unlist(outdf %>%select(dc_1_r_0)))[-1278], na.rm = TRUE)),
color="red", linetype="dashed") +
theme_bw() +
labs(x="CMD level",
y="Ratio between total output/input decay rates") +
scale_x_discrete(labels=c("1"="100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="0")) +
scale_fill_discrete(name = "Ribosome\nprot index") +
theme(
text = element_text(size = 13),
legend.position = "none"
)
##############
outdf <- tibble(matrix(NA, ncol=nrow(dc.r.df)-1, nrow=4839)) #contains all the total input decay rates
for (i in 1:(nrow(dc.r.df)-1)) # these 16 columns are all the same, all equal to simInputFeatures$mRNAabundance*simInputFeatures$mRNADecRateNeymotin_sec
{
inf <- read.table(paste0(basefolder, expID, "/input/allGenesDecrEqualsSynrWithScaling_", dc.r.df$paraCombo[i+1], "_S.cer.mRNA.ini.abndc.syn.dec"))
outdf[, i] <- (inf[, 4]*inf[, 2])
}
outdf <- totdr/outdf
colnames(outdf) <- dc.r.df$paraCombo[2:nrow(dc.r.df)]
outdf %>%
mutate(mRNAabundance=simInputFeatures$mRNAabundance, mRNADecRateNeymotin_sec=simInputFeatures$mRNADecRateNeymotin_sec, ORF=simInputFeatures$ORF) %>%
pivot_longer(names_to = "paraCombo", values_to = "ratioVal", cols = !c(mRNAabundance, mRNADecRateNeymotin_sec, ORF)) %>%
filter(paraCombo == "dc_0_r_1", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A") %>%
ggplot(aes(x=mRNAabundance, y=ratioVal)) +
geom_point() +
theme_bw() +
scale_x_log10()
Fig. S
l %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YCR024C-B", mRNAabundance != 1) %>%
mutate(relativeFano = RMVPS/RMPSR) %>%
ggplot(aes(x=RMPSR, y=relativeFano)) +
geom_point(size=0.1) +
scale_x_log10() +
scale_y_log10() +
labs(x= "Realtive mean protein synthesis rate",
y = "Relative fano factor in protein synthesis rate",
title = "") +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.1, label.y.npc = 0.3, size=3) +
theme_bw()
allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YCR024C-B", mRNAabundance != 1) %>%
ggplot(aes(x=MRD, y=RMVTE)) +
geom_point(size=0.1) +
scale_x_log10() +
scale_y_log10() +
labs(x= "Mean ribosome density",
y = "Relative mean of variance in translation efficiency",
title = "") +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.1, label.y.npc = 0.3, size=3) +
theme_bw()
allSimInputOutput %>%
filter(paraCombo == "dc_1_r_0", mRNADecRateNeymotin_sec != 0, ORF != "YCR024C-B", mRNAabundance != 1) %>%
ggplot(aes(x=MMDP, y=mRNADecRateNeymotin_sec)) +
geom_point(size=0.1) +
scale_x_log10() +
scale_y_log10() +
labs(x= "Mean ribosome density",
y = "Relative mean of variance in translation efficiency",
title = "") +
geom_smooth(method="lm") +
stat_cor(aes(label=paste(..r.label.., sep = "~`, `~")), label.x.npc = 0.1, label.y.npc = 0.3, size=3) +
theme_bw()
Figure S.
# calculating the mean number of free ribos (averaged over simuTime and techReps) for all dc.r.paraCombos
# RMFR = relative mean free ribo
mfr <- c()
for(i in 1:nrow(dc.r.df)) # loop through the dc/r parameter space to calculate the mean free ribo
{
# free_ribo averaged by simuTime and techReps
mfr <- c(mfr, mean(h5read(simOutputH5, paste("free_ribo_tRNA_perMin", dc.r.df$paraCombo[i], "ribo", sep="/")), na.rm = TRUE))
# set na.rm=T because in rep 66 again there's an NA at the last minute, which won't affect the overall mean
}
rmfr <- mfr/mfr[1]
rmfr_df <- data.frame(RMFR = rmfr,
MFR = mfr,
para = dc.r.df$para)
# rmfr_df can be found in exp0_prepPlots.Rmd
rmfr_df %>%
left_join(., dc.r.df, by ="para") %>%
filter(paraCombo != "mRNAconstant") %>%
select(RMFR, dc, r) %>%
spread(dc, RMFR) %>%
select(-r) %>%
colMeans() %>%
tibble() %>%
mutate(dc=as.character(seq(0, 1, by=0.2))) %>%
`colnames<-`(c("RMFRmeanByCoTrans", "dc")) %>%
mutate(cotrans = paste0(as.numeric(dc)*100, "%")) %>%
ggplot(aes(x=cotrans, y=RMFRmeanByCoTrans)) +
geom_point() +
theme_bw() +
labs ( title = "",
x ="Co-translational decay proportion",
y = "Mean free ribosomes (relative to mRNA constant)") +
theme(text = element_text(size = 13),
panel.grid = element_blank()) +
scale_x_discrete(limits = c("100%", "80%", "60%", "40%", "20%", "0%"))
make_heatmap <- function(orderVar, outputVar, legendName, titleY)
{
colorvec <- quantile(allSimInputOutput[[outputVar]])
tmp <- (allSimInputOutput%>%filter(paraCombo == "dc_1_r_0"))[, c("ORF", orderVar)]
tmp <- tmp[order(tmp[, 2], decreasing = T), ]
tmp$newid_dc1r0 <- 1:4839
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant") %>%
left_join(., tmp[, c("ORF", "newid_dc1r0")], by = "ORF") %>%
mutate(dc_fct=factor(dc, levels=c("1", "0.8", "0.6", "0.4", "0.2", "0"))) %>%
ggplot(aes_string(x = "r",
y = "factor(newid_dc1r0)",
fill = outputVar)) +
geom_raster() +
theme_bw() +
scale_fill_gradientn(colours = c("#377eb8", "white", "#e41a1c"), # blue white red
values = scales::rescale(colorvec), name=legendName) +
facet_wrap(~dc_fct, nrow=1, labeller=labeller(dc_fct=c("1"="Co-trans 100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="0"))) +
labs ( x = "Ribosome protection index r",
y = titleY,
title = "") +
theme(text = element_text(size = 18),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
panel.border = element_blank(), # remove the grid lines in facet_grid
panel.spacing=unit(0, "lines")) + # reset the spacing between facets
guides(fill = guide_colourbar(barwidth = 1, barheight = 10)) +
scale_x_discrete(expand = c(0, 0)) # remove the extra space beyond xlim
}
# 1st var= the variable column the sorting is based on
# 2nd var= the variable column presented in the heatmap
# 3rd var= the legend text
# 4th var= y-axis title
make_heatmap("RMTE", "RMTE", "Relative\nmean translation\nefficiency", "Genes ranked by the first column")
make_heatmap("RMVTE", "RMVTE", "Relative mean\nof the variance\nin translation\nefficiency", "Genes ranked by the first column")
########################################################## add a plot for mRNAs marked for decay
colorvec <- quantile((allSimInputOutput%>% filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A"))$MMDP)
tmp <- (allSimInputOutput%>%filter(paraCombo == "dc_1_r_0"))[, c("ORF", "RMTE")]
tmp <- tmp[order(tmp[, 2], decreasing = T), ]
tmp$newid_dc1r0 <- 1:4839
allSimInputOutput %>%
mutate(dc_fct=factor(dc, levels=c("1", "0.8", "0.6", "0.4", "0.2", "0"))) %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", dc != 0) %>%
left_join(., tmp[, c("ORF", "newid_dc1r0")], by = "ORF") %>%
ggplot(aes(x = r,
y = factor(newid_dc1r0),
#y = as.character(newid_geneLength_codon), # genes are sorted by geneLength_codon within each group
fill = MMDP)) +
geom_raster() +
theme_bw() +
scale_fill_gradientn(colours = c("#377eb8", "white", "#e41a1c"), # blue white red
values = scales::rescale(colorvec), name="mRNAs marked\nfor decay ratio") +
facet_wrap(~dc_fct, nrow=1, labeller=labeller(dc_fct=c("1"="Co-trans 100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="0%"))) +
labs ( x = "Ribosome protection index w",
y = "Genes ranked by the first column in translation efficiency plot",
title = "") +
theme(text = element_text(size = 18),
plot.title = element_text(size=rel(1.5)),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
panel.border = element_blank(), # remove the grid lines in facet_grid
panel.spacing=unit(0, "lines")) + # reset the spacing between facets
guides(fill = guide_colourbar(barwidth = 1, barheight = 10)) +
scale_x_discrete(expand = c(0, 0)) # remove the extra space beyond xlim
########################################################## add another plot for mRNAs marked for decay
colorvec <- quantile((allSimInputOutput%>% filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A"))$MMDP)
tmp <- (allSimInputOutput%>%filter(paraCombo == "dc_1_r_0"))[, c("ORF", "RMVTE")]
tmp <- tmp[order(tmp[, 2], decreasing = T), ]
tmp$newid_dc1r0 <- 1:4839
allSimInputOutput %>%
mutate(dc_fct=factor(dc, levels=c("1", "0.8", "0.6", "0.4", "0.2", "0"))) %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A", dc != 0) %>%
left_join(., tmp[, c("ORF", "newid_dc1r0")], by = "ORF") %>%
ggplot(aes(x = r,
y = factor(newid_dc1r0),
fill = MMDP)) +
geom_raster() +
theme_bw() +
scale_fill_gradientn(colours = c("#377eb8", "white", "#e41a1c"), # blue white red
values = scales::rescale(colorvec), name="mRNAs marked\nfor decay ratio") +
facet_wrap(~dc_fct, nrow=1, labeller=labeller(dc_fct=c("1"="Co-trans 100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="0%"))) +
labs ( x = "Ribosome protection index w",
y = "Genes ranked by the first column in translation efficiency plot",
title = "") +
theme(text = element_text(size = 18),
plot.title = element_text(size=rel(1.5)),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
panel.border = element_blank(), # remove the grid lines in facet_grid
panel.spacing=unit(0, "lines")) + # reset the spacing between facets
guides(fill = guide_colourbar(barwidth = 1, barheight = 10)) +
scale_x_discrete(expand = c(0, 0)) # remove the extra space beyond xlim
# 1st var= the variable column the sorting is based on
# 2nd var= the variable column presented in the heatmap
# 3rd var= the legend text
# 4th var= y-axis title
make_heatmap("RMPSR", "RMPSR", "Relative\nmean protein\nsyn rate", "Genes ranked by the first column")
make_heatmap("RMVPS", "RMVPS", "Relative\nmean of variance in\nprotein syn rate", "Genes ranked by the first column")
make_heatmap_tmp <- function(orderVar, outputVar, legendName, titleY)
{
colorvec <- quantile(allSimInputOutput[[outputVar]])
tmp <- (allSimInputOutput%>%filter(paraCombo == "dc_1_r_0"))[, c("ORF", orderVar)]
tmp <- tmp[order(tmp[, 2], decreasing = T), ]
tmp$newid_dc1r0 <- 1:4839
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", RMVTBR != Inf) %>%
left_join(.,tmp[, c("ORF", "newid_dc1r0")], by = "ORF") %>%
mutate(dc_fct=factor(dc, levels=c("1", "0.8", "0.6", "0.4", "0.2", "0"))) %>%
ggplot(aes_string(x = "r",
y = "factor(newid_dc1r0)",
fill = outputVar)) +
geom_raster() +
theme_bw() +
scale_fill_gradientn(colours = c("#377eb8", "white", "#e41a1c"), # blue white red
values = scales::rescale(colorvec), name=legendName) +
facet_wrap(~dc_fct, nrow=1, labeller=labeller(dc_fct=c("1"="Co-trans 100%", "0.8"="80%", "0.6"="60%", "0.4"="40%", "0.2"="20%", "0"="0"))) +
labs ( x = "Ribosome protection index r",
y = titleY,
title = "") +
theme(text = element_text(size = 18),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
panel.border = element_blank(), # remove the grid lines in facet_grid
panel.spacing=unit(0, "lines")) + # reset the spacing between facets
guides(fill = guide_colourbar(barwidth = 1, barheight = 10)) +
scale_x_discrete(expand = c(0, 0)) # remove the extra space beyond xlim
}
make_heatmap_tmp("RMTE", "RMVTBR", "Relative\nvariance in total\nbound ribosomes", "Genes ranked by the first column in relative TE")
make_heatmap("MML", "MML", "Mean of mRNA\nlife-times", "Genes ranked by the first column")
###############################################################
colorvec <- quantile((allSimInputOutput%>% filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A"))$RMRD)
tmp <- (allSimInputOutput%>%filter(paraCombo == "dc_1_r_0"))[, c("ORF", "RMTE")]
tmp <- tmp[order(tmp[, 2], decreasing = T), ]
tmp$newid_dc1r0 <- 1:4839
allSimInputOutput %>%
filter(paraCombo != "mRNAconstant", mRNADecRateNeymotin_sec != 0, ORF != "YER053C-A") %>%
left_join(., tmp[, c("ORF", "newid_dc1r0")], by = "ORF") %>%
ggplot(aes(x = r,
y = factor(newid_dc1r0),
fill = RMRD)) +
geom_raster() +
theme_bw() +
scale_fill_gradientn(colours = c("#377eb8", "white", "#e41a1c"), # blue white red
values = scales::rescale(colorvec), name="Relative mean\nribo density") +
facet_wrap(~dc, nrow=1, labeller=labeller(dc=c("1"="Co-trans 100%", "0.8"="0.8", "0.6"="0.6", "0.4"="0.4", "0.2"="0.2", "0"="0"))) +
labs ( x = "Ribosome protection index",
y = "Genes ranked by the first column for translation efficiency",
title = "") +
theme(text = element_text(size = 18),
plot.title = element_text(size=rel(1.5)),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
panel.border = element_blank(), # remove the grid lines in facet_grid
panel.spacing=unit(0, "lines")) + # reset the spacing between facets
guides(fill = guide_colourbar(barwidth = 1, barheight = 10)) +
scale_x_discrete(expand = c(0, 0)) # remove the extra space beyond xlim
LS0tCnRpdGxlOiAiRmlndXJlcyBmb3IgbWFudXNjcmlwdCIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpMb2FkIGxpYnJhcmllcyBhbmQgcHVibGljIHZhcmlhYmxlcwpgYGB7ciwgaW5jbHVkZT1GQUxTRX0gCiMgVGhpcyBjaHVuayB3aWxsIGJlIGV2YWx1YXRlZCBidXQgdGhlIG91dHB1dCBpcyBzdXBwcmVzc2VkCnJtYXJrZG93bjo6cmVuZGVyKCIuLi8uLi9wdWJsaWNWYXJpYWJsZXMvY3JlYXRlUHVibGljVmFyaWFibGVzLlJtZCIpCmBgYAoKYGBge3J9CiMgRmlsZSB0aGF0IGNvbnRhaW5zIHNpbXVsYXRpb24gb3V0cHV0IGRhdGEgaW4gYSBIREY1IGRpcmVjdG9yeSBzdHJ1Y3R1cmUgc3BlY2lmaWVkIGluICIvcHVibGljVmFyaWFibGVzL2NyZWF0ZVB1YmxpY1ZhcmlhYmxlcy5SbWQiCnNpbU91dHB1dEg1IDwtIHBhc3RlMCgiLi4vLi4vZGF0YVByb2Nlc3Npbmcvc2ltT3V0cHV0SDVEYXRhLyIsIGV4cGVyaW1lbnRJRCwgIl9vdXRwdXQuaDUiKQoKIyBBIGNvbXByZWhlbnNpdmUgdGFibGUgdGhhdCBjb250YWlucyBhbGwgc2ltdWxhdGlvbiBpbnB1dCBhbmQgY2FsY3VsYXRlZCBvdXRwdXQgbWV0cmljcwphbGxTaW1JbnB1dE91dHB1dCA8LSByZWFkX2ZlYXRoZXIoIi4uL2FsbFNpbUlucHV0T3V0cHV0LmZlYXRoZXIiKQoKIyBUaGlzIGZvbGRlciBjb250YWlucyByYXcgb3V0cHV0IGZpbGVzIGZyb20gdGhlIHNpbXVsYXRpb25zLiBUaGlzIGlzIG5lZWRlZCBmb3IgY2FsY3VsYXRlX3BhcmFfc3BfbWNwc3IoKQpyYXdTaW1PdXRGb2xkZXIgPC0gIi90ZWFtL2JhdGNoX1NNT1ROVC9leHBlcmltZW50MV9vdXRwdXQiCgojIFdoZXJlIGZpZ3VyZXMgYXJlIHN0b3JlZApmaWd1cmVCYXNlRm9sZGVyIDwtICIuLi9maWd1cmVzLyIKYGBgCgpWYWxpZGF0aW9uOiBjb21wYXJlIHRoZSBwcm90ZWluIHN5bnRoZXNpcyByYXRlcyB3aXRoIFdlaW5iZXJnIDIwMTYKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0Kd2VpbmJlcmdEYXRhIDwtIHJlYWRfdHN2KCIuLi9leHRlcm5hbERhdGEvd2VpbmJlcmdfc3ludGhlc2lzLnR4dCIpCgp2YWxpZGF0aW9uUGxvdCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUgCiAgZmlsdGVyKHBhcmFDb21ibyA9PSAibVJOQWNvbnN0YW50IikgJT4lIAogIHNlbGVjdChPUkYsIHBhcmFDb21ibywgTVBTUiwgZGMsIHIpICU+JQogIGxlZnRfam9pbih3ZWluYmVyZ0RhdGFbLCBjKCJPUkYiLCAiUyIpXSwgYnkgPSAiT1JGIikgJT4lCiAgbXV0YXRlKFNfcGVyTWluPVMqNjAsCiAgICAgICAgIG5ld2NvbWJvPWZhY3RvcihwYXJhQ29tYm8sIGxldmVscz1kYy5yLmRmJHBhcmFDb21ib1syOjI1XSkpICU+JQogIGdncGxvdChhZXMoeD1NUFNSLCB5PVNfcGVyTWluKSkgKwogICAgZ2VvbV9hYmxpbmUobGluZXR5cGU9ImRhc2hlZCIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikgKwogICAgc3RhdF9jb3IoYWVzKGxhYmVsPXBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjEsIGxhYmVsLnkubnBjID0gMC43LCBzaXplPTEwKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIHRoZW1lX2J3KCkgKwogICAgbGFicyh4PSJNZWFuIHByb3RlaW4gc3ludGhlc2lzIHJhdGVzIGZvciBtUk5BIGNvbnN0YW50IiwKICAgICAgICAgeT0iUHJvdGVpbiBzeW50aGVzaXMgcmF0ZSBlc3RpbWF0ZXMgYnkgV2VpbmJlcmcgZXQgYWwgMjAxNiIpCgp2YWxpZGF0aW9uUGxvdAoKd3JpdGVfcmRzKHZhbGlkYXRpb25QbG90LCAiLi4vZmlndXJlcy92YWxpZGF0aW9uUGxvdC5yZHMiKQoKCnRtcCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUgCiAgICBmaWx0ZXIocGFyYUNvbWJvID09ICJtUk5BY29uc3RhbnQiKSAlPiUgCiAgICBzZWxlY3QoT1JGLCBwYXJhQ29tYm8sIE1QU1IpICU+JQogICAgbGVmdF9qb2luKHdlaW5iZXJnRGF0YVssIGMoIk9SRiIsICJTIildLCBieSA9ICJPUkYiKSAlPiUKICAgIG11dGF0ZShTX3Blck1pbj1TKjYwKSAKCiMgcXVpY2sgdHJ5IG9mIHBpcGluZyB0aGUgdCB0ZXN0IGRpZG4ndCB3b3JrLi4KdC50ZXN0KHRtcCRTX3Blck1pbiwgdG1wJE1QU1IsIHBhaXJlZCA9IFRSVUUpCmBgYAoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KZmlnUzBfYSA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm89PSJtUk5BY29uc3RhbnQifHBhcmFDb21ibz09ImRjXzFfcl8wIiwgT1JGIT0iWUVSMDUzQy1BIikgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9TVBTUiwgeT1QTVBTUiwgY29sb3IgPSBwYXJhQ29tYm8pKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsKICAgIGdlb21fYWJsaW5lKGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJ3aGl0ZSIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICAgICkgKwogICAgICAgIGxhYnMoeCA9ICdNZWFuIG9mIHByb3RlaW4gc3ludGhlc2lzIHJhdGUnfihtaW5eLTEpLAogICAgICAgICAgICAgeSA9ICdQcmVkaWN0ZWQgbWVhbiBvZiBwcm90ZWluIHN5bnRoZXNpcyByYXRlJ34obWluXi0xKSkgKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLCBsYWJlbHM9YygibVJOQWNvbnN0YW50Ij0ibVJOQWNvbnN0YW50IiwgImRjXzFfcl8wIj0ibVJOQXZhcnlpbmciKSwgdmFsdWVzID0gYygiIzFGNzhCNCIsICIjRkY3RjAwIikpICsKICAgICAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikgKwogICAgICAgIHN0YXRfY29yKGFlcyhsYWJlbD1wYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjcsIGxhYmVsLnkubnBjID0gMC40LCBzaXplPTUpICsKICAgICAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgICAgIHNjYWxlX3lfbG9nMTAoKQoKZmlnUzBfYQp3cml0ZV9yZHMoZmlnUzBfYSwiLi4vZmlndXJlcy9maWdTMF9hLnJkcyIpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpmaWdTMF9iIDwtIGFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibz09ImRjXzFfcl8wIiwgT1JGIT0iWUVSMDUzQy1BIikgJT4lCiAgICBzZWxlY3QocGFyYUNvbWJvLCBPUkYsIE1WUFMsIFBNUFNSLCBtUk5BU3luUmF0ZVRvdGFsX3NlYykgJT4lCiAgICBtdXRhdGUobVJOQVN5blJhdGVUb3RhbF9taW4gPSBtUk5BU3luUmF0ZVRvdGFsX3NlYyo2MCwKICAgICAgICAgICBhZGRpdGl2ZVZhciA9IFBNUFNSICsgbVJOQVN5blJhdGVUb3RhbF9taW4sCiAgICAgICAgICAgbXVsdGlwbGljYXRpdmVWYXIgPSBQTVBTUiAqIG1STkFTeW5SYXRlVG90YWxfbWluICsgUE1QU1JeMiptUk5BU3luUmF0ZVRvdGFsX21pbiArIFBNUFNSKm1STkFTeW5SYXRlVG90YWxfbWluXjIpICU+JSAKICAgIHNlbGVjdChPUkYsIE1WUFMsIGFkZGl0aXZlVmFyLCBtdWx0aXBsaWNhdGl2ZVZhcikgJT4lIAogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gInByZWRpY3RlZFZhciIsIHZhbHVlc190byA9ICJwcmVkaWN0ZWRWYXJWYWx1ZSIsIGNvbHMgPSAtYyhPUkYsTVZQUykpICU+JSAKICAgIGdncGxvdChhZXMoeD1NVlBTLCB5PXByZWRpY3RlZFZhclZhbHVlLCBjb2xvciA9IHByZWRpY3RlZFZhcikpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkgKwogICAgZ2VvbV9hYmxpbmUobGluZXR5cGU9ImRhc2hlZCIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgKSArCiAgICAgICAgbGFicyh4ID0gJ1ZhcmlhbmNlIG9mIHByb3RlaW4gc3ludGhlc2lzIHJhdGUnfihtaW5eLTIpLAogICAgICAgICAgICAgeSA9ICdQcmVkaWN0ZWQgdmFyaWFuY2Ugb2YgcHJvdGVpbiBzeW50aGVzaXMgcmF0ZSd+KG1pbl4tMikpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0iIiwgbGFiZWxzPWMoIm1STkFjb25zdGFudCI9Im1STkFjb25zdGFudCIsICJkY18xX3JfMCI9Im1STkF2YXJ5aW5nIiksIHZhbHVlcyA9IGMoIiMxRjc4QjQiLCAiI0ZGN0YwMCIpKSArCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgICAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC43LCBsYWJlbC55Lm5wYyA9IDAuNCwgc2l6ZT01KSArCiAgICAgICAgc2NhbGVfeF9sb2cxMCgpICsKICAgICAgICBzY2FsZV95X2xvZzEwKCkKCmZpZ1MwX2IKd3JpdGVfcmRzKGZpZ1MwX2IsICIuLi9maWd1cmVzL2ZpZ1MwX2IucmRzIikKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmZpZ1MwX2MgPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvPT0iZGNfMV9yXzAiLCBPUkYhPSJZRVIwNTNDLUEiKSAlPiUKICAgIHNlbGVjdChwYXJhQ29tYm8sIE9SRiwgTVBTUiwgUk1QU1IpICU+JSAKICAgIGdncGxvdChhZXMoeCA9IE1QU1IsIHkgPSBSTVBTUikpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkgKwogICAgI2dlb21fYWJsaW5lKGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICApICsKICAgICAgICBsYWJzKHggPSAnbWVhbiBwcm90IHN5biByYXRlIGZvciBtUk5BdmFyeWluZyd+KG1pbl4tMSksCiAgICAgICAgICAgICB5ID0gJ3JlbGF0aXZlIG1lYW4gcHJvdCBzeW4gcmF0ZSBmb3IgbVJOQXZhcnlpbmcnfihtaW5eLTEpKSArCiAgICAgICAgI3NjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLCBsYWJlbHM9YygibVJOQWNvbnN0YW50Ij0ibVJOQWNvbnN0YW50IiwgImRjXzFfcl8wIj0ibVJOQXZhcnlpbmciKSwgdmFsdWVzID0gYygiIzFGNzhCNCIsICIjRkY3RjAwIikpICsKICAgICAgICBnZW9tX3Ntb290aCgpICsKICAgICAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC43LCBsYWJlbC55Lm5wYyA9IDAuNCwgc2l6ZT01KSArCiAgICAgICAgc2NhbGVfeF9sb2cxMCgpIAoKZmlnUzBfYwp3cml0ZV9yZHMoZmlnUzBfYywgIi4uL2ZpZ3VyZXMvZmlnUzBfYy5yZHMiKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZmlnUzBfZCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm89PSJkY18xX3JfMCIsIE9SRiE9IllFUjA1M0MtQSIpICU+JQogICAgc2VsZWN0KHBhcmFDb21ibywgT1JGLCBNUFNSLCBSTVBTUikgJT4lCiAgICBhcnJhbmdlKE1QU1IpICU+JSAKICAgICMgbXV0YXRlKGJpbk5hbWVzID0gYyh1bmxpc3QobGFwcGx5KDE6MTksIGZ1bmN0aW9uKHgpe3JlcCh4LDI1NCl9KSksIHJlcCgyMCwxMikpKSAlPiUgICMgYmluIGFsbCA0ODM4IGdlbmVzIGludG8gMjAgYmlucywgZWFjaCBjb250YWlucyBzYW1lIG51bWJlciBvZiBnZW5lcyBvcmRlcmVkIGJ5IHRoZWlyIE1QU1IKICAgICMgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGJpbk5hbWVzLCBsZXZlbHMgPSAxOjIwKSwgeSA9IFJNUFNSKSkgKwogICAgbXV0YXRlKGJpbk5hbWVzID0gYyh1bmxpc3QobGFwcGx5KDE6OSwgZnVuY3Rpb24oeCl7cmVwKHgsNTM3KX0pKSwgcmVwKDEwLDUpKSkgJT4lICAjIGJpbiBhbGwgNDgzOCBnZW5lcyBpbnRvIDEwIGJpbnMsIGVhY2ggY29udGFpbnMgc2FtZSBudW1iZXIgb2YgZ2VuZXMgb3JkZXJlZCBieSB0aGVpciBNUFNSCiAgICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoYmluTmFtZXMsIGxldmVscyA9IDE6MTApLCB5ID0gUk1QU1IpKSArCiAgICBnZW9tX2JveHBsb3QoKSArCiAgICAjZ2VvbV9hYmxpbmUobGluZXR5cGU9ImRhc2hlZCIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJ3aGl0ZSIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICAgICkgKwogICAgICAgIGxhYnMoeCA9ICdtZWFuIHByb3Qgc3luIHJhdGUgZm9yIG1STkF2YXJ5aW5nJ34obWluXi0xKSwKICAgICAgICAgICAgIHkgPSAncmVsYXRpdmUgbWVhbiBwcm90IHN5biByYXRlIGZvciBtUk5BdmFyeWluZyd+KG1pbl4tMSkpICsKICAgICAgICAjc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsIGxhYmVscz1jKCJtUk5BY29uc3RhbnQiPSJtUk5BY29uc3RhbnQiLCAiZGNfMV9yXzAiPSJtUk5BdmFyeWluZyIpLCB2YWx1ZXMgPSBjKCIjMUY3OEI0IiwgIiNGRjdGMDAiKSkgKwogICAgICAgIGdlb21fc21vb3RoKCkgKwogICAgICAgIHN0YXRfY29yKGFlcyhsYWJlbD1wYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjcsIGxhYmVsLnkubnBjID0gMC40LCBzaXplPTUpIAoKZmlnUzBfZAp3cml0ZV9yZHMoZmlnUzBfZCwgIi4uL2ZpZ3VyZXMvZmlnUzBfZC5yZHMiKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZmlnUzBfZSA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm89PSJkY18xX3JfMCIsIE9SRiE9IllFUjA1M0MtQSIpICU+JQogICAgc2VsZWN0KHBhcmFDb21ibywgT1JGLCBNUFNSLCBSTVBTUikgJT4lCiAgICBhcnJhbmdlKE1QU1IpICU+JSAKICAgICMgbXV0YXRlKGJpbk5hbWVzID0gYyh1bmxpc3QobGFwcGx5KDE6MTksIGZ1bmN0aW9uKHgpe3JlcCh4LDI1NCl9KSksIHJlcCgyMCwxMikpKSAlPiUgICMgYmluIGFsbCA0ODM4IGdlbmVzIGludG8gMjAgYmlucywgZWFjaCBjb250YWlucyBzYW1lIG51bWJlciBvZiBnZW5lcyBvcmRlcmVkIGJ5IHRoZWlyIE1QU1IKICAgICMgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGJpbk5hbWVzLCBsZXZlbHMgPSAxOjIwKSwgeSA9IFJNUFNSKSkgKwogICAgbXV0YXRlKGJpbk5hbWVzID0gYyh1bmxpc3QobGFwcGx5KDE6OSwgZnVuY3Rpb24oeCl7cmVwKHgsNTM3KX0pKSwgcmVwKDEwLDUpKSkgJT4lICAjIGJpbiBhbGwgNDgzOCBnZW5lcyBpbnRvIDEwIGJpbnMsIGVhY2ggY29udGFpbnMgc2FtZSBudW1iZXIgb2YgZ2VuZXMgb3JkZXJlZCBieSB0aGVpciBNUFNSCiAgICBncm91cF9ieShiaW5OYW1lcykgJT4lIAogICAgbXV0YXRlKHRlc3QgPSBSTVBTUj4xKSAlPiUgCiAgICAjbXV0YXRlKGZyZXFSTVBTUmFib3ZlMSA9IHN1bSh0ZXN0KS9uKCkpICU+JSAKICAgIHN1bW1hcml6ZShmcmVxUk1QU1JhYm92ZTEgPSBzdW0odGVzdCkvbigpKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoYmluTmFtZXMsIGxldmVscyA9IDE6MTApLCB5ID0gZnJlcVJNUFNSYWJvdmUxKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknKSArCiAgICAjZ2VvbV9hYmxpbmUobGluZXR5cGU9ImRhc2hlZCIpICsKICAgICNnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICApICsKICAgICAgICBsYWJzKHggPSAnYmlucyBvZiBnZW5lcycsCiAgICAgICAgICAgICB5ID0gJ2ZyZXEgb2YgcmVsLiBtZWFuIHByb3Qgc3luIHJhdGUgYWJvdmUgMSBpbiBlYWNoIGJpbicpCgpmaWdTMF9lCndyaXRlX3JkcyhmaWdTMF9lLCAiLi4vZmlndXJlcy9maWdTMF9lLnJkcyIpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpmaWdTMF9mIDwtIGFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibz09ImRjXzFfcl8wIiwgT1JGIT0iWUVSMDUzQy1BIikgJT4lCiAgICBzZWxlY3QocGFyYUNvbWJvLCBPUkYsIG1STkFhYnVuZGFuY2UsIFJNUFNSKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBtUk5BYWJ1bmRhbmNlLCB5ID0gUk1QU1IpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsKICAgICNnZW9tX2FibGluZShsaW5ldHlwZT0iZGFzaGVkIikgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGU9ImRhc2hlZCIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgKSArCiAgICAgICAgbGFicyh4ID0gJ21STkEgYWJ1bmRhbmNlcycsCiAgICAgICAgICAgICB5ID0gJ3JlbGF0aXZlIG1lYW4gcHJvdCBzeW4gcmF0ZSBmb3IgbVJOQXZhcnlpbmcnfihtaW5eLTEpKSArCiAgICAgICAgI3NjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLCBsYWJlbHM9YygibVJOQWNvbnN0YW50Ij0ibVJOQWNvbnN0YW50IiwgImRjXzFfcl8wIj0ibVJOQXZhcnlpbmciKSwgdmFsdWVzID0gYygiIzFGNzhCNCIsICIjRkY3RjAwIikpICsKICAgICAgICBnZW9tX3Ntb290aCgpICsKICAgICAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC43LCBsYWJlbC55Lm5wYyA9IDAuNCwgc2l6ZT01KSArCiAgICAgICAgc2NhbGVfeF9sb2cxMCgpIAoKZmlnUzBfZgp3cml0ZV9yZHMoZmlnUzBfZiwgIi4uL2ZpZ3VyZXMvZmlnUzBfZi5yZHMiKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZmlnUzBfZyA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm89PSJkY18xX3JfMCIsIE9SRiE9IllFUjA1M0MtQSIpICU+JQogICAgc2VsZWN0KHBhcmFDb21ibywgT1JGLCBDQUksIFJNUFNSKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBDQUksIHkgPSBSTVBTUikpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkgKwogICAgI2dlb21fYWJsaW5lKGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICApICsKICAgICAgICBsYWJzKHggPSAnQ0FJJywKICAgICAgICAgICAgIHkgPSAncmVsYXRpdmUgbWVhbiBwcm90IHN5biByYXRlIGZvciBtUk5BdmFyeWluZyd+KG1pbl4tMSkpICsKICAgICAgICAjc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsIGxhYmVscz1jKCJtUk5BY29uc3RhbnQiPSJtUk5BY29uc3RhbnQiLCAiZGNfMV9yXzAiPSJtUk5BdmFyeWluZyIpLCB2YWx1ZXMgPSBjKCIjMUY3OEI0IiwgIiNGRjdGMDAiKSkgKwogICAgICAgIGdlb21fc21vb3RoKCkgKwogICAgICAgIHN0YXRfY29yKGFlcyhsYWJlbD1wYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjcsIGxhYmVsLnkubnBjID0gMC40LCBzaXplPTUpIAoKZmlnUzBfZwp3cml0ZV9yZHMoZmlnUzBfZywgIi4uL2ZpZ3VyZXMvZmlnUzBfZy5yZHMiKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZmlnUzBfaCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm89PSJkY18xX3JfMCIsIE9SRiE9IllFUjA1M0MtQSIpICU+JQogICAgc2VsZWN0KHBhcmFDb21ibywgT1JGLCBpbmlQcm9iLCBSTVBTUikgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gaW5pUHJvYiwgeSA9IFJNUFNSKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC41KSArCiAgICAjZ2VvbV9hYmxpbmUobGluZXR5cGU9ImRhc2hlZCIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJ3aGl0ZSIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICAgICkgKwogICAgICAgIGxhYnMoeCA9ICd0cmFuc2xhdGlvbiBpbml0aWF0aW9uIHByb2JhYmlsaXR5JywKICAgICAgICAgICAgIHkgPSAncmVsYXRpdmUgbWVhbiBwcm90IHN5biByYXRlIGZvciBtUk5BdmFyeWluZyd+KG1pbl4tMSkpICsKICAgICAgICAjc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsIGxhYmVscz1jKCJtUk5BY29uc3RhbnQiPSJtUk5BY29uc3RhbnQiLCAiZGNfMV9yXzAiPSJtUk5BdmFyeWluZyIpLCB2YWx1ZXMgPSBjKCIjMUY3OEI0IiwgIiNGRjdGMDAiKSkgKwogICAgICAgIGdlb21fc21vb3RoKCkgKwogICAgICAgIHN0YXRfY29yKGFlcyhsYWJlbD1wYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjcsIGxhYmVsLnkubnBjID0gMC40LCBzaXplPTUpICsKICAgICAgICBzY2FsZV94X2xvZzEwKCkgCgpmaWdTMF9oCndyaXRlX3JkcyhmaWdTMF9oLCAiLi4vZmlndXJlcy9maWdTMF9oLnJkcyIpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpmaWdTMF9pIDwtIGFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibz09ImRjXzFfcl8wIiwgT1JGIT0iWUVSMDUzQy1BIikgJT4lCiAgICAjbXV0YXRlKGludEN0cmxPck5vdCA9IGlmZWxzZShtUk5BRGVjUmF0ZU5leW1vdGluX3NlYz09MCwiaW50Q3RybCIsIm5vbkN0cmwiKSkgJT4lIAogICAgI3NlbGVjdChwYXJhQ29tYm8sIE9SRiwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1QU1IsIGludEN0cmxPck5vdCkgJT4lIAogICAgc2VsZWN0KHBhcmFDb21ibywgT1JGLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTVBTUikgJT4lIAogICAgI2dncGxvdChhZXMoeCA9IGdlbmVMZW5ndGhfY29kb24sIHkgPSBSTVBTUiwgY29sb3IgPSBpbnRDdHJsT3JOb3QpKSArCiAgICBnZ3Bsb3QoYWVzKHggPSBnZW5lTGVuZ3RoX2NvZG9uLCB5ID0gUk1QU1IpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsKICAgICNnZW9tX2FibGluZShsaW5ldHlwZT0iZGFzaGVkIikgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGU9ImRhc2hlZCIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgKSArCiAgICAgICAgbGFicyh4ID0gJ2dlbmUgbGVuZ3RoIChjb2RvbiknLAogICAgICAgICAgICAgeSA9ICdyZWxhdGl2ZSBtZWFuIHByb3Qgc3luIHJhdGUgZm9yIG1STkF2YXJ5aW5nJ34obWluXi0xKSkgKwogICAgICAgICNzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0iIiwgbGFiZWxzPWMoIm1STkFjb25zdGFudCI9Im1STkFjb25zdGFudCIsICJkY18xX3JfMCI9Im1STkF2YXJ5aW5nIiksIHZhbHVlcyA9IGMoIiMxRjc4QjQiLCAiI0ZGN0YwMCIpKSArCiAgICAgICAgZ2VvbV9zbW9vdGgoKSArCiAgICAgICAgc3RhdF9jb3IoYWVzKGxhYmVsPXBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuNywgbGFiZWwueS5ucGMgPSAwLjQsIHNpemU9NSkgKwogICAgICAgIHNjYWxlX3hfbG9nMTAoKSAKCmZpZ1MwX2kKd3JpdGVfcmRzKGZpZ1MwX2ksICIuLi9maWd1cmVzL2ZpZ1MwX2kucmRzIikKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmZpZ1MwX2ogPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvPT0iZGNfMV9yXzAiLCBPUkYhPSJZRVIwNTNDLUEiKSAlPiUKICAgIHNlbGVjdChwYXJhQ29tYm8sIE9SRiwgbVJOQURlY1JhdGVOZXltb3Rpbl9taW4sIFJNUFNSKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBtUk5BRGVjUmF0ZU5leW1vdGluX21pbiwgeSA9IFJNUFNSKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC41KSArCiAgICAjZ2VvbV9hYmxpbmUobGluZXR5cGU9ImRhc2hlZCIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJ3aGl0ZSIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICAgICkgKwogICAgICAgIGxhYnMoeCA9ICdtUk5BIGRlY2F5IHJhdGVzIGZyb20gTmV5bW90aW4gZGF0YSAobWluKScsCiAgICAgICAgICAgICB5ID0gJ3JlbGF0aXZlIG1lYW4gcHJvdCBzeW4gcmF0ZSBmb3IgbVJOQXZhcnlpbmcnfihtaW5eLTEpKSArCiAgICAgICAgI3NjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLCBsYWJlbHM9YygibVJOQWNvbnN0YW50Ij0ibVJOQWNvbnN0YW50IiwgImRjXzFfcl8wIj0ibVJOQXZhcnlpbmciKSwgdmFsdWVzID0gYygiIzFGNzhCNCIsICIjRkY3RjAwIikpICsKICAgICAgICBnZW9tX3Ntb290aCgpICsKICAgICAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC43LCBsYWJlbC55Lm5wYyA9IDAuNCwgc2l6ZT01KSArCiAgICAgICAgc2NhbGVfeF9sb2cxMCgpIAoKZmlnUzBfagp3cml0ZV9yZHMoZmlnUzBfaiwgIi4uL2ZpZ3VyZXMvZmlnUzBfai5yZHMiKQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmZpZ1MwX2sgPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvIT0gIm1STkFjb25zdGFudCIpICU+JSAKICAgIHNlbGVjdChkYywgciwgUk1GUikgJT4lIAogICAgdW5pcXVlKCkgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gZGMsIHkgPSBSTUZSLCBjb2xvciA9IGZhY3RvcihyKSkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX2xpbmUoKSArCiAgICAjIHRoZW1lX2J3KCkgKwogICAgIyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAjICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICMgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICMgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAjICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICAjICAgKSArCiAgICAgICAgbGFicyh4ID0gJ0NNRCBsZXZlbHMnLAogICAgICAgICAgICAgeSA9ICdSZWxhdGl2ZSBtZWFuIGZyZWUgcmlib3NvbWVzJykgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiUmlibyBwcm90ZWN0aW9uIGluZGV4IikKCmZpZ1MwX2sKd3JpdGVfcmRzKGZpZ1MwX2ssICIuLi9maWd1cmVzL2ZpZ1MwX2sucmRzIikKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZmlnUzBfbCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICBmaWx0ZXIocGFyYUNvbWJvPT0iZGNfMF9yXzEiLCBPUkYhPSJZRVIwNTNDLUEiKSAlPiUgI3JlbW92ZSB0aGUgZ2VuZSB3aXRoIHRoZSA0NTBtaW4gSEwKICAjIGZpbHRlcihwYXJhQ29tYm89PSJkY18wX3JfMSIsIE9SRiE9IllFUjA1M0MtQSIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjPT0wKSAlPiUgCiAgIyBzZWxlY3QoIk9SRiIsICJSTVBTUiIsICJSTUZSIikgJT4lIAogIG11dGF0ZShpbnRDdHJsT3JOb3QgPSBpZmVsc2UobVJOQURlY1JhdGVOZXltb3Rpbl9zZWM9PTAsImludEN0cmwiLCJub25DdHJsIikpICU+JSAKICBzZWxlY3QoIk9SRiIsICJSTVBTUiIsICJpbnRDdHJsT3JOb3QiKSAlPiUgCiAgI3NlbGVjdCgiT1JGIiwgIlJNUFNSIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2RlbnNpdHkoYWVzKHg9Uk1QU1IsIGNvbG9yID0gaW50Q3RybE9yTm90KSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNiwgMC42KSwKICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHggPSAiUmVsLiBtZWFuIHByb3RlaW4gc3ludGhlc2lzIHJhdGUiKSArCiAgICAjc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlJNVlBTIj0iYmxhY2siKSkgKyAgCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiaW50Q3RybCI9ImJsdWUiLCAibm9uQ3RybCI9ImJsYWNrIikpICsgIAogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpIAoKZmlnUzBfbAp3cml0ZV9yZHMoZmlnUzBfbCwgIi4uL2ZpZ3VyZXMvZmlnUzBfbC5yZHMiKQpgYGAKCgoKRmlnIFMxCmBgYHtyIGZpZy5oZWlnaHQgPSA2LCBmaWcud2lkdGg9MTB9CnRyaWFsX21STkFjb3VudCA8LSByZWFkX2ZlYXRoZXIoIi4uLy4uL3NpbXVsYXRpb25zL3RyaWFsbVJOQWNvdW50RGF0YS90cmlhbF9tUk5BY291bnQuZmVhdGhlciIpCnRyaWFsX21STkFjb3VudAoKZmlndXJlUzEgPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBsZWZ0X2pvaW4oLiwgdHJpYWxfbVJOQWNvdW50WyxjKCJwYXJhQ29tYm8iLCJPUkYiLCJ0cmlhbFJNTUMiKV0sIGJ5ID0gYygicGFyYUNvbWJvIj0icGFyYUNvbWJvIiwgIk9SRiI9Ik9SRiIpKSAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIpICU+JQogICAgc2VsZWN0KHBhcmFDb21ibywgUk1NQywgdHJpYWxSTU1DLCBkYywgcikgJT4lCiAgICBgY29sbmFtZXM8LWAoYygicGFyYUNvbWJvIiwgIkFmdGVyU2NhbGluZyIsICJCZWZvcmVTY2FsaW5nIiwgImRjIiwgInIiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAia2V5IiwgdmFsdWVzX3RvID0gIlJNTUN2YWx1ZSIsIGNvbHMgPSAyOjMpICU+JQogICAgZ2dwbG90KGFlcyh4PVJNTUN2YWx1ZSwgY29sb3I9a2V5KSkgKwogICAgICAgIGdlb21fZGVuc2l0eSgpICsKICAgICAgICBmYWNldF9ncmlkKGRjfnIsIGxhYmVsbGVyPWxhYmVsbGVyKGRjPWMoIjEiPSIxMDAlIiwgIjAuOCI9IjgwJSIsICIwLjYiPSI2MCUiLCAiMC40Ij0iNDAlIiwgIjAuMiI9IjIwJSIsICIwIj0iQ28tdHJucyAwJSIpLCByPWMoIjAiPSJSaWJvIHByb3QgaW5keCA9IDAiLCAiMC4xIj0iMC4xIiwgIjAuNCI9IjAuNCIsICIxIj0iMSIpLCBsYWJlbF9wYXJzZWQpKSArIAogICAgICAgIGxhYnModGl0bGUgPSAiRmlnIFMxOiBtUk5BIGNvdW50cyB3aGVuIHZhcnlpbmcgYXJlIGxhcmVnZWx5IGVxdWFsIHRvIHdoZW4gdGhleSBhcmUgY29uc3RhbnQgXG5hZnRlciBzY2FsaW5nIHRoZSBtUk5BIHN5bnRoZXNpcyByYXRlcyIsIAogICAgICAgICAgICAgeD0iUmVsYXRpdmUgbWVhbiBtUk5BIGNvdW50IikgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cygpICsKICAgICAgICB0aGVtZV9idygpICsKICAgICAgICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEzKSwgCiAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCmZpZ3VyZVMxCgp3cml0ZV9yZHMoZmlndXJlUzEsICIuLi9maWd1cmVzL2ZpZ3VyZVMxLnJkcyIpCiNnZ3NhdmUocGFzdGUwKGZpZ3VyZUJhc2VGb2xkZXIsICJmaWd1cmVzMS9zX2ZpZ18xLnBuZyIpLCBkcGk9MTAwLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDgpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwphbGxTaW1JbnB1dE91dHB1dCAlPiUgCiAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IikgJT4lIAogIHNlbGVjdChwYXJhQ29tYm8sIFJNTUMsIGRjLCByKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUk1NQykpICsgCiAgICAgIGdlb21fZGVuc2l0eSgpICsKICAgICAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlcj1sYWJlbGxlcihkYz1jKCIxIj0iMTAwJSIsICIwLjgiPSI4MCUiLCAiMC42Ij0iNjAlIiwgIjAuNCI9IjQwJSIsICIwLjIiPSIyMCUiLCAiMCI9IkNvLXRybnMgMCUiKSwgcj1jKCIwIj0iUmlibyBwcm90IGluZHggPSAwIiwgIjAuMSI9IjAuMSIsICIwLjQiPSIwLjQiLCAiMSI9IjEiKSwgbGFiZWxfcGFyc2VkKSkgKyAKICAgICAgbGFicyh4PSJSZWxhdGl2ZSBtZWFuIG1STkEgY291bnQgYWZ0ZXIgc2NhbGluZyIpICsKICAgICAgc2NhbGVfeV9jb250aW51b3VzKCkgKwogICAgICB0aGVtZV9idygpICsKICAgICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMyksIAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIpICU+JQogICAgc2VsZWN0KHBhcmFDb21ibywgUk1NQywgZGMsIHIsIGdlbmVMZW5ndGhfY29kb24pICU+JQogICAgbXV0YXRlKHNPUmwgPSBpZmVsc2UoZ2VuZUxlbmd0aF9jb2RvbiA+PTUxMiwgImxvbmciLCAic2hvcnQiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9Uk1NQywgY29sb3I9c09SbCkpICsKICAgICAgICBnZW9tX2RlbnNpdHkoKSArCiAgICAgICAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlcj1sYWJlbGxlcihkYz1jKCIxIj0iMTAwJSIsICIwLjgiPSI4MCUiLCAiMC42Ij0iNjAlIiwgIjAuNCI9IjQwJSIsICIwLjIiPSIyMCUiLCAiMCI9IkNvLXRybnMgMCUiKSwgcj1jKCIwIj0iUmlibyBwcm90IGluZHggPSAwIiwgIjAuMSI9IjAuMSIsICIwLjQiPSIwLjQiLCAiMSI9IjEiKSwgbGFiZWxfcGFyc2VkKSkgKyAKICAgICAgICBsYWJzKHg9IlJlbGF0aXZlIG1lYW4gbVJOQSBjb3VudCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoKSArCiAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgCiAgICAgICAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLCAKICAgICAgICAgICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IikgJT4lCiAgICBzZWxlY3QocGFyYUNvbWJvLCBSTU1DLCBkYywgciwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMpICU+JQogICAgbXV0YXRlKGZPUnMgPSBpZmVsc2UobVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgPj0wLjAwMDk0MzE2MjgsICJmYXN0IiwgInNsb3ciKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9Uk1NQywgY29sb3I9Zk9ScykpICsKICAgICAgICBnZW9tX2RlbnNpdHkoKSArCiAgICAgICAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlcj1sYWJlbGxlcihkYz1jKCIxIj0iMTAwJSIsICIwLjgiPSI4MCUiLCAiMC42Ij0iNjAlIiwgIjAuNCI9IjQwJSIsICIwLjIiPSIyMCUiLCAiMCI9IkNvLXRybnMgMCUiKSwgcj1jKCIwIj0iUmlibyBwcm90IGluZHggPSAwIiwgIjAuMSI9IjAuMSIsICIwLjQiPSIwLjQiLCAiMSI9IjEiKSwgbGFiZWxfcGFyc2VkKSkgKyAKICAgICAgICBsYWJzKHg9IlJlbGF0aXZlIG1lYW4gbVJOQSBjb3VudCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoKSArCiAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgCiAgICAgICAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLCAKICAgICAgICAgICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpCgoKYWxsU2ltSW5wdXRPdXRwdXQlPiUKICBmaWx0ZXIoT1JGIT0iWUVSMDUzQy1BIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMhPTAsIHBhcmFDb21ibyE9Im1STkFjb25zdGFudCIpICU+JQogIG11dGF0ZShkY19mY3Q9ZmFjdG9yKGRjLCBsZXZlbHM9YygiMSIsICIwLjgiLCAiMC42IiwgIjAuNCIsICIwLjIiLCAiMCIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRjX2ZjdCwgeT1STU1DLCBmaWxsPXIpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDAuMSkgKwogICMgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdD1tZWRpYW4oYXMubnVtZXJpYyh1bmxpc3QoYWxsU2ltSW5wdXRPdXRwdXQlPiVmaWx0ZXIoT1JGIT0iWUVSMDUzQy1BIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMhPTAsIHBhcmFDb21ibz09ImRjXzFfcl8wIiklPiVzZWxlY3QoUk1NRFIpKSksIG5hLnJtID0gVFJVRSkpLCBjb2xvcj0icmVkIiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHg9IkNNRCBsZXZlbCIsCiAgICAgICB5PSJSZWxhdGl2ZSBtZWFuIG1STkEgY291bnQiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiMSI9IjEwMCUiLCAiMC44Ij0iODAlIiwgIjAuNiI9IjYwJSIsICIwLjQiPSI0MCUiLCAiMC4yIj0iMjAlIiwgIjAiPSIwIikpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiUmlib3NvbWVcbnByb3QgaW5kZXgiKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICApCiAgCgphbGxTaW1JbnB1dE91dHB1dCAlPiUKICBncm91cF9ieShwYXJhQ29tYm8pICU+JQogIHN1bW1hcmlzZShNID0gbWVhbihSTU1DKSkgJT4lCiAgYXJyYW5nZShkZXNjKE0pKQoKYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgZ3JvdXBfYnkoZGMpICU+JQogIHN1bW1hcmlzZShNID0gbWVhbihSTU1DKSkgJT4lCiAgYXJyYW5nZShkZXNjKE0pKQoKYGBgCgoKCkZpZy4gd2FzIFMzLCBub3cgUzIKYGBge3IgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aCA9ICAxMH0KZmlndXJlUzIgPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IiwgT1JGICE9ICJZRVIwNTNDLUEiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBNTUMsIHkgPSBNVk1DKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkgKwogIGdlb21fYWJsaW5lKGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBmYWNldF9ncmlkKGRjfnIsIGxhYmVsbGVyID0gbGFiZWxsZXIoZGMgPSBjKCIxIiA9ICIxMDAlIiwgIjAuOCIgPSAiODAlIiwgIjAuNiIgPSAiNjAlIiwgIjAuNCIgPSAiNDAlIiwgIjAuMiIgPSAiMjAlIiwgIjAiID0gIkNvLXRybnMgMCUiKSwgciA9IGMoIjAiID0gIlJpYm8gcHJvdCBpbmR4ICA9ICAwIiwgIjAuMSIgPSAiMC4xIiwgIjAuNCIgPSAiMC40IiwgIjEiID0gIjEiKSwgbGFiZWxfcGFyc2VkKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICApICsKICAgICAgbGFicyh4ID0gJ01lYW4gb2YgbVJOQSBjb3VudCcsCiAgICAgICAgICAgeSA9ICdWYXJpYW5jZSBvZiBtUk5BIGNvdW50JykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuNywgbGFiZWwueS5ucGMgPSAwLjQsIHNpemUgPSA1KSArCiAgICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICAgIHNjYWxlX3lfbG9nMTAoKQoKZmlndXJlUzIKd3JpdGVfcmRzKGZpZ3VyZVMyLCAiLi4vZmlndXJlcy9maWd1cmVTMi5yZHMiKQoKYGBgCgoKCgp3YXMgRmlnIFM0LCBub3cgUzM6IFNlcXVlbmNlIGZlYXR1cmVzIGNvcnJlbGF0ZSB3aXRoIHRoZSBmYW5vIGZhY3RvciBvZiBwcm90ZWluIHN5bnRoZXNpcyByYXRlcyBmb3IgbVJOQSBjb25zdGFudApgYGB7ciBmaWcuaGVpZ2h0ID0gMywgZmlnLndpZHRoID0gOH0KcGxvdF9mdW4xIDwtIGZ1bmN0aW9uKHZhcjEsIHZhcjIpeyBhbGxTaW1JbnB1dE91dHB1dCU+JSAgI3ZhcjE6Ik1lYW5Qcm90ZWluU3luUmF0ZSIuLiB2YXIyOiJtUk5BY29uc3RhbnQiLCAiZGNfMV9yXzAiCiAgZmlsdGVyKHBhcmFDb21ibyA9PSB2YXIyLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwKSAlPiUKICBzZWxlY3QoT1JGLCBNUFNSLCBNVlBTLCBpbmlQcm9iX2xvZzEwLCBtUk5BYWJ1bmRhbmNlX2xvZzEwLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlY19sb2cxMCwgQ0FJLCBnZW5lTGVuZ3RoX2NvZG9uX2xvZzEwKSAlPiUKICBtdXRhdGUoZmFub19wcm90U3luID0gTVZQUy9NUFNSKSAlPiUKICBmaWx0ZXIoZmFub19wcm90U3luPjAuMykgJT4lICAjIGZpbHRlciBvdXQgdGhlIHR3byBvdXRsaWVycwogIGBjb2xuYW1lczwtYChwYXN0ZTAoIiIsYygiT1JGIiwgIk1lYW5Qcm90ZWluU3luUmF0ZSIsICJWYXJpYW5jZVByb3RlaW5TeW5SYXRlIiwgImluaVByb2JfbG9nMTAiLCAibVJOQUxldmVsX2xvZzEwIiwgIkRlY1JhdGVfbG9nMTAiLCAiQ0FJIiwgImdlbmVMZW5ndGhfbG9nMTAiLCAiZmFub19wcm90U3luUmF0ZSIpKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhYyhPUkYsTWVhblByb3RlaW5TeW5SYXRlLCBWYXJpYW5jZVByb3RlaW5TeW5SYXRlLCBmYW5vX3Byb3RTeW5SYXRlKSkgJT4lCiAgZ2dwbG90KGFlc19zdHJpbmcoeCA9ICJmZWF0dXJlVmFscyIsIHkgPSB2YXIxKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC41KSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3cgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgICB0aGVtZV9idygpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuNCwgbGFiZWwueS5ucGMgPSAwLjEzLCBzaXplID0gMykgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9IHZhcjEpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAKICAgICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIgICAgICN0byBwdXQgdGhlIHN0cmlwIGxhYmVscyBiZWxvdyB4LWF4aXMKKQp9CgpmaWd1cmVTMyA8LSBwbG90X2Z1bjEoImZhbm9fcHJvdFN5blJhdGUiLCAibVJOQWNvbnN0YW50IikKCmZpZ3VyZVMzCndyaXRlX3JkcyhmaWd1cmVTMywgIi4uL2ZpZ3VyZXMvZmlndXJlUzMucmRzIikKYGBgCgpXYXMgRmlnIFM1LCBub3cgUzQuIApgYGB7ciBmaWcuaGVpZ2h0ID0gNCwgZmlnLndpZHRoID0gNn0KIyBNTURQID0gbVJOQXMgbWFya2VkIGZvciBkZWdyYWRhdGlvbiBwcm9wb3J0aW9uIGFtb25nIG1lYW4gdG90YWwgbVJOQQpmaWd1cmVTNCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCkgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSBNTURQLCB5ID0gUk1QU1IpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4ID0gIlByb3BvcnRpb24gb2YgbVJOQSBtYXJrZWQgZm9yIGRlY2F5IiwgCiAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIG9mIHByb3RlaW4gc3ludGhlc2lzIHJhdGVzIiwgCiAgICAgICAgdGl0bGUgPSAiIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMSwgbGFiZWwueS5ucGMgPSAwLjMsIHNpemUgPSAzKSArIAogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplID0gMTMpKQoKZmlndXJlUzQKd3JpdGVfcmRzKGZpZ3VyZVM0LCAiLi4vZmlndXJlcy9maWd1cmVTNC5yZHMiKQoKYGBgCkZpZy4gUzUKYGBge3IgZmlnLmhlaWdodCA9IDQsIGZpZy53aWR0aCA9IDZ9CmZpZ3VyZVM1IDwtIGFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibz09ImRjXzFfcl8wIiwgT1JGIT0iWUVSMDUzQy1BIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMhPTApICU+JSAKICAgIHNlbGVjdCgiT1JGIiwgIkNWUFMiLCAiQ1ZNQyIsICJwYXJhQ29tYm8iKSAlPiUgI3JlbW92ZSB0aGUgZ2VuZSB3aXRoIHRoZSA0NTBtaW4gSEwKICAgIGdncGxvdChhZXMoeD1DVk1DLCB5PUNWUFMsIGNvbG91cj1wYXJhQ29tYm8pKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsKICAgIGdlb21fYWJsaW5lKGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICApICsKICAgICAgICBsYWJzKHggPSJDViBmb3IgbVJOQSBjb3VudCBwZXIgbWluIiwKICAgICAgICAgICAgIHkgPSAiQ1YgZm9yIHByb3RlaW4gc3ludGhlc2lzIHJhdGUiKSArCiAgICAgICAgI3NjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWU9IiIsbGFiZWxzPWMoIkNvLXRyYW5zIDEwMCUgUmlib1Byb3RlY3QgMCIpKSArCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgICAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsIGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuNSwgbGFiZWwueS5ucGMgPSAwLjMsIHNpemU9NSkgKwogICAgICAgIHNjYWxlX3hfbG9nMTAoKSArICMgbm90IGFibGUgdG8gYWRkIHRoZSBpbnNldCBpZiBpIGtlZXAgdGhlIGxvZyBzY2FsZXMgZm9yIGVpdGhlciB4IG9yIHkKICAgICAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLCBsYWJlbHM9YygiQ28tdHJhbnMgMTAwJSBSaWJvUHJvdGVjdCAwIiksIHZhbHVlcyA9IGMoImRjXzFfcl8wIiA9ICJibGFjayIpKQoKZmlndXJlUzUKd3JpdGVfcmRzKGZpZ3VyZVM1LCAiLi4vZmlndXJlcy9maWd1cmVTNS5yZHMiKQpgYGAKCgpGaWcgUzY6IHJlbGF0aXZlIENWID0gQ1Ygb2YgdGhlIHByb3RlaW4gc3ludGhlc2lzIHJhdGUvQ1Ygb2YgdGhlIG1STkEgY291bnQKYGBge3IgZmlnLmhlaWdodCA9IDMsIGZpZy53aWR0aCA9IDh9CmZpZ3VyZVM2IDwtIGFsbFNpbUlucHV0T3V0cHV0ICU+JQogIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZQ1IwMjRDLUIiKSAlPiUgICAgIyJZQ1IwMjRDLUIiIGlzIGFuIG91dGxpZXIgd2hvc2UgcmVsQ1YgPSAyMwogIG11dGF0ZShyZWxDViA9IENWUFMvQ1ZNQykgJT4lCiAgc2VsZWN0KE9SRiwgcmVsQ1YsIGluaVByb2JfbG9nMTAsIG1STkFhYnVuZGFuY2VfbG9nMTAsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjX2xvZzEwLCBDQUksIGdlbmVMZW5ndGhfY29kb25fbG9nMTApICU+JQogICAgYGNvbG5hbWVzPC1gKHBhc3RlMCgiIiwgYygiT1JGIiwgIlJlbGF0aXZlX0NWIiwgImluaVByb2JfbG9nMTAiLCAibVJOQUxldmVsX2xvZzEwIiwgIkRlY1JhdGVfbG9nMTAiLCAiQ0FJIiwgImdlbmVMZW5ndGhfbG9nMTAiKSkpICU+JQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJmZWF0dXJlIiwgdmFsdWVzX3RvID0gImZlYXR1cmVWYWxzIiwgLWMoT1JGLCBSZWxhdGl2ZV9DVikpICU+JQogIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gUmVsYXRpdmVfQ1YpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsKICAgICAgZmFjZXRfd3JhcCh+ZmVhdHVyZSwgc2NhbGVzID0gImZyZWUiLCBucm93ID0gMSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgICB0aGVtZV9idygpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogICAgICBzdGF0X2NvcihhZXMobGFiZWwgPSBwYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjE1LCBsYWJlbC55Lm5wYyA9IDAuOCwgc2l6ZSA9IDMpICsKICAgIGxhYnMoeCA9ICIiLAogICAgICAgICB5ID0gIlJlbGF0aXZlIENWIikgKwogICAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAgCiAgICAgICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIikgICAgICN0byBwdXQgdGhlIHN0cmlwIGxhYmVscyBiZWxvdyB4LWF4aXMKCmZpZ3VyZVM2CndyaXRlX3JkcyhmaWd1cmVTNiwgIi4uL2ZpZ3VyZXMvZmlndXJlUzYucmRzIikKCmBgYAoKRmlnLiBTNzogCmBgYHtyIGZpZy5oZWlnaHQgPSA0LCBmaWcud2lkdGggPSA3fQpmaWd1cmVTNyA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIikgJT4lCiAgICBzZWxlY3QoTVRULCBNTURQLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTU1EUikgJT4lCiAgICBgY29sbmFtZXM8LWAgKGMoIk1lYW5UcmFuc1RpbWUiLCAibVJOQU1hcmtkRGVjUHJvcCIsICJnZW5lTGVuZ3RoX2NvZG9uIiwgIlJlbGF0aXZlRGVjUmF0ZSIpKSAlPiUKICAgIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJmZWF0dXJlIiwgdmFsdWVzX3RvID0gImZlYXR1cmVWYWxzIiwgIWdlbmVMZW5ndGhfY29kb24pICU+JQogICAgZ2dwbG90KGFlcyh4ID0gZmVhdHVyZVZhbHMsIHkgPSBnZW5lTGVuZ3RoX2NvZG9uKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZV94IiwgbnJvdyA9IDEsIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4ID0gIiIsCiAgICAgICAgeSA9ICJHZW5lIGxlbmd0aCAoY29kb24pIiwKICAgICAgICB0aXRsZSA9ICJkY18xX3JfMCIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsgCiAgICBzdGF0X2NvcihhZXMobGFiZWwgPSBwYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCwgYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMSwgc2l6ZSA9IDMpICsgCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiKQoKZmlndXJlUzcKd3JpdGVfcmRzKGZpZ3VyZVM3LCAiLi4vZmlndXJlcy9maWd1cmVTNy5yZHMiKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMV9yXzEiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwLCBPUkYgIT0gIllFUjA1M0MtQSIsT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJNZWFuVHJhbnNUaW1lIiwgIm1STkFNYXJrZERlY1Byb3AiLCAiZ2VuZUxlbmd0aF9jb2RvbiIsICJSZWxhdGl2ZURlY1JhdGUiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiZmVhdHVyZSIsIHZhbHVlc190byA9ICJmZWF0dXJlVmFscyIsICFnZW5lTGVuZ3RoX2NvZG9uKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gZ2VuZUxlbmd0aF9jb2RvbikpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogICAgZmFjZXRfd3JhcCh+ZmVhdHVyZSwgc2NhbGVzID0gImZyZWVfeCIsIG5yb3cgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnMoeCA9ICIiLAogICAgICAgIHkgPSAiR2VuZSBsZW5ndGggKGNvZG9uKSIsCiAgICAgICAgdGl0bGUgPSAiZGNfMV9yXzEiKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMSwgc2l6ZSA9IDMpICsgCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiKQoKCnRtcCA8LSBhbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLE9SRiAhPSAiWUdSMTY5Qy1BIiwgT1JGICE9ICJZTFIxMDZDIixPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgICAgbXV0YXRlKFJEUiA9IE1NRFIvbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMpICU+JQogICAgICAgc2VsZWN0KFJNVEUsIGdlbmVMZW5ndGhfY29kb24sIFJEUikgCnN1bW1hcnkobG0oUk1URX5nZW5lTGVuZ3RoX2NvZG9uK1JEUiwgdG1wKSkKCiMgTU1EUCA9IG1STkFzIG1hcmtlZCBmb3IgZGVncmFkYXRpb24gcHJvcG9ydGlvbiBhbW9uZyBtZWFuIHRvdGFsIG1STkEKIyBNVFQgPSBtZWFuIHRyYW5zbGF0aW9uIHRpbWUKYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18xX3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDApICU+JQogICAgZ2dwbG90KGFlcyh4ID0gTVRULCB5ID0gTU1EUCkpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHggPSAiTWVhbiB0cmFuc2xhdGlvbiB0aW1lIiwKICAgICAgICB5ID0gIlByb3BvcnRpb24gb2YgbVJOQSBtYXJrZWQgZm9yIGRlY2F5IiwKICAgICAgICB0aXRsZSA9ICIiKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsIGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMSwgbGFiZWwueS5ucGMgPSAwLjMsIHNpemUgPSAzKSArIAogICAgdGhlbWVfYncoKSAKCgphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzAuMl9yXzAiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwLCBPUkYgIT0gIllFUjA1M0MtQSIsIE9SRiAhPSAiWUdSMTY5Qy1BIiwgT1JGICE9ICJZTFIxMDZDIiwgT1JGICE9ICJZQ1IwMjRDLUIiKSAlPiUKICAgIHNlbGVjdChNVFQsIE1NRFAsIGdlbmVMZW5ndGhfY29kb24sIFJNTURSKSAlPiUKICAgIGBjb2xuYW1lczwtYCAoYygiTWVhblRyYW5zVGltZSIsICJtUk5BTWFya2REZWNQcm9wIiwgImdlbmVMZW5ndGhfY29kb24iLCAiUmVsYXRpdmVEZWNSYXRlIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhZ2VuZUxlbmd0aF9jb2RvbikgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSBmZWF0dXJlVmFscywgeSA9IGdlbmVMZW5ndGhfY29kb24pKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgIGZhY2V0X3dyYXAofmZlYXR1cmUsIHNjYWxlcyA9ICJmcmVlX3giLCBucm93ID0gMSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHggPSAiIiwKICAgICAgICB5ID0gIkdlbmUgbGVuZ3RoIChjb2RvbikiLAogICAgICAgIHRpdGxlID0gImRjXzAuMl9yXzAiKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMSwgc2l6ZSA9IDMpICsgCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiKQoKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMC4yX3JfMSIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJNZWFuVHJhbnNUaW1lIiwgIm1STkFNYXJrZERlY1Byb3AiLCAiZ2VuZUxlbmd0aF9jb2RvbiIsICJSZWxhdGl2ZURlY1JhdGUiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiZmVhdHVyZSIsIHZhbHVlc190byA9ICJmZWF0dXJlVmFscyIsICFnZW5lTGVuZ3RoX2NvZG9uKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gZ2VuZUxlbmd0aF9jb2RvbikpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogICAgZmFjZXRfd3JhcCh+ZmVhdHVyZSwgc2NhbGVzID0gImZyZWVfeCIsIG5yb3cgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnMoeCA9ICIiLAogICAgICAgIHkgPSAiR2VuZSBsZW5ndGggKGNvZG9uKSIsCiAgICAgICAgdGl0bGUgPSAiZGNfMC4yX3JfMSIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsgCiAgICBzdGF0X2NvcihhZXMobGFiZWwgPSBwYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCwgYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMSwgc2l6ZSA9IDMpICsgCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiKQpgYGAKCgoKRmlnLiBTOApgYGB7ciBmaWcuaGVpZ2h0ID0gNCwgZmlnLndpZHRoID0gN30KZmlndXJlUzggPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18xX3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KFJNVEUsIE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJSZWxNZWFuVEUiLCAiTWVhblRyYW5zVGltZSIsICJtUk5BTWFya2REZWNQcm9wIiwgImdlbmVMZW5ndGhfY29kb24iLCAiUmVsYXRpdmVEZWNSYXRlIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhUmVsTWVhblRFKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gUmVsTWVhblRFKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZV94IiwgbnJvdyA9IDEsIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4ID0gIiIsCiAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIFRFIiwKICAgICAgICB0aXRsZSA9ICJkY18xX3JfMCIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsgCiAgICBzdGF0X2NvcihhZXMobGFiZWwgPSBwYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCwgYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMSwgc2l6ZSA9IDMpICsgCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOCkpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAKICAgICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIpCgpmaWd1cmVTOAp3cml0ZV9yZHMoZmlndXJlUzgsICIuLi9maWd1cmVzL2ZpZ3VyZVM4LnJkcyIpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMC44X3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KFJNVEUsIE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJSZWxNZWFuVEUiLCAiTWVhblRyYW5zVGltZSIsICJtUk5BTWFya2REZWNQcm9wIiwgImdlbmVMZW5ndGhfY29kb24iLCAiUmVsYXRpdmVEZWNSYXRlIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhUmVsTWVhblRFKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gUmVsTWVhblRFKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZV94IiwgbnJvdyA9IDEsIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4ID0gIiIsCiAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIFRFIiwKICAgICAgICB0aXRsZSA9ICJkY18wLjhfcl8wIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4xLCBzaXplID0gMykgKyAKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44KSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIikKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMC42X3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KFJNVEUsIE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJSZWxNZWFuVEUiLCAiTWVhblRyYW5zVGltZSIsICJtUk5BTWFya2REZWNQcm9wIiwgImdlbmVMZW5ndGhfY29kb24iLCAiUmVsYXRpdmVEZWNSYXRlIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhUmVsTWVhblRFKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gUmVsTWVhblRFKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZV94IiwgbnJvdyA9IDEsIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4ID0gIiIsCiAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIFRFIiwKICAgICAgICB0aXRsZSA9ICJkY18wLjZfcl8wIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4xLCBzaXplID0gMykgKyAKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44KSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIikKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMC40X3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KFJNVEUsIE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJSZWxNZWFuVEUiLCAiTWVhblRyYW5zVGltZSIsICJtUk5BTWFya2REZWNQcm9wIiwgImdlbmVMZW5ndGhfY29kb24iLCAiUmVsYXRpdmVEZWNSYXRlIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhUmVsTWVhblRFKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gUmVsTWVhblRFKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZV94IiwgbnJvdyA9IDEsc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHggPSAiIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIG1lYW4gVEUiLAogICAgICAgIHRpdGxlID0gImRjXzAuNF9yXzAiKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsIGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMywgbGFiZWwueS5ucGMgPSAwLjEsIHNpemUgPSAzKSArIAogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjgpKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAgCiAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiKQoKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMC4yX3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICAgc2VsZWN0KFJNVEUsIE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogICAgYGNvbG5hbWVzPC1gIChjKCJSZWxNZWFuVEUiLCAiTWVhblRyYW5zVGltZSIsICJtUk5BTWFya2REZWNQcm9wIiwgImdlbmVMZW5ndGhfY29kb24iLCAiUmVsYXRpdmVEZWNSYXRlIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbHMiLCAhUmVsTWVhblRFKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IGZlYXR1cmVWYWxzLCB5ID0gUmVsTWVhblRFKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZV94IiwgbnJvdyA9IDEsIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4ID0gIiIsCiAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIFRFIiwKICAgICAgICB0aXRsZSA9ICJkY18wLjJfcl8wIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4xLCBzaXplID0gMykgKyAKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44KSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIikKCgphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzBfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIikgJT4lCiAgICBzZWxlY3QoUk1URSwgTVRULCBNTURQLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTU1EUikgJT4lCiAgICBgY29sbmFtZXM8LWAgKGMoIlJlbE1lYW5URSIsICJNZWFuVHJhbnNUaW1lIiwgIm1STkFNYXJrZERlY1Byb3AiLCAiZ2VuZUxlbmd0aF9jb2RvbiIsICJSZWxhdGl2ZURlY1JhdGUiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiZmVhdHVyZSIsIHZhbHVlc190byA9ICJmZWF0dXJlVmFscyIsICFSZWxNZWFuVEUpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gZmVhdHVyZVZhbHMsIHkgPSBSZWxNZWFuVEUpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgIGZhY2V0X3dyYXAofmZlYXR1cmUsIHNjYWxlcyA9ICJmcmVlX3giLCBucm93ID0gMSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHggPSAiIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIG1lYW4gVEUiLAogICAgICAgIHRpdGxlID0gImRjXzBfcl8wIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4xLCBzaXplID0gMykgKyAKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44KSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAKICAgICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIpCgphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8xIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIikgJT4lCiAgICBzZWxlY3QoUk1URSwgTVRULCBNTURQLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTU1EUikgJT4lCiAgICBgY29sbmFtZXM8LWAgKGMoIlJlbE1lYW5URSIsICJNZWFuVHJhbnNUaW1lIiwgIm1STkFNYXJrZERlY1Byb3AiLCAiZ2VuZUxlbmd0aF9jb2RvbiIsICJSZWxhdGl2ZURlY1JhdGUiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiZmVhdHVyZSIsIHZhbHVlc190byA9ICJmZWF0dXJlVmFscyIsICFSZWxNZWFuVEUpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gZmVhdHVyZVZhbHMsIHkgPSBSZWxNZWFuVEUpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgIGZhY2V0X3dyYXAofmZlYXR1cmUsIHNjYWxlcyA9ICJmcmVlX3giLCBucm93ID0gMSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHggPSAiIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIG1lYW4gVEUiLAogICAgICAgIHRpdGxlID0gImRjXzFfcl8xIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4xLCBzaXplID0gMykgKyAKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOCkpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAKICAgICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIpCgoKYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18wLjJfcl8xIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIikgJT4lCiAgICBzZWxlY3QoUk1URSwgTVRULCBNTURQLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTU1EUikgJT4lCiAgICBgY29sbmFtZXM8LWAgKGMoIlJlbE1lYW5URSIsICJNZWFuVHJhbnNUaW1lIiwgIm1STkFNYXJrZERlY1Byb3AiLCAiZ2VuZUxlbmd0aF9jb2RvbiIsICJSZWxhdGl2ZURlY1JhdGUiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiZmVhdHVyZSIsIHZhbHVlc190byA9ICJmZWF0dXJlVmFscyIsICFSZWxNZWFuVEUpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gZmVhdHVyZVZhbHMsIHkgPSBSZWxNZWFuVEUpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgIGZhY2V0X3dyYXAofmZlYXR1cmUsIHNjYWxlcyA9ICJmcmVlX3giLCBucm93ID0gMSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgc2NhbGVfeF9sb2cxMCgpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHggPSAiIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIG1lYW4gVEUiLAogICAgICAgIHRpdGxlID0gImRjXzAuMl9yXzEiKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsIGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMywgbGFiZWwueS5ucGMgPSAwLjEsIHNpemUgPSAzKSArIAogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjgpKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAgCiAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiKQoKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMV9yXzAiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwLCBPUkYgIT0gIllFUjA1M0MtQSIsIE9SRiAhPSAiWUdSMTY5Qy1BIiwgT1JGICE9ICJZTFIxMDZDIiwgT1JGICE9ICJZQ1IwMjRDLUIiKSAlPiUKICAgIHNlbGVjdChNTURQLCBSTU1EUikgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSBNTURQLCB5ID0gUk1NRFIpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgIGxhYnMoeCA9ICJNTURQIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIGRlY2F5IHJhdGVzIiwKICAgICAgICB0aXRsZSA9ICJkY18xX3JfMCIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsgCiAgICBzdGF0X2NvcihhZXMobGFiZWwgPSBwYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCwgYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMSwgc2l6ZSA9IDMpICsgCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOCkpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAKICAgICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIpCgojIE1NRFAgPSBtUk5BcyBtYXJrZWQgZm9yIGRlZ3JhZGF0aW9uIHByb3BvcnRpb24KYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18wLjJfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIikgJT4lCiAgICBzZWxlY3QoTU1EUCwgUk1NRFIpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gTU1EUCwgeSA9IFJNTURSKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnMoeCA9ICJNTURQIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIGRlY2F5IHJhdGVzIiwKICAgICAgICB0aXRsZSA9ICJkY18wLjJfcl8wIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4xLCBzaXplID0gMykgKyAKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44KSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIikKYGBgCgpGaWcuIFM5CmBgYHtyIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSAxMH0KZmlndXJlUzkgPC0gYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIiwgZGMgIT0gMCkgJT4lCiAgI3NlbGVjdChSTVRFLCBNVFQsIE1NRFAsIGdlbmVMZW5ndGhfY29kb24sIFJNTURSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBNTURQLCB5ID0gUk1URSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICBmYWNldF9ncmlkKGRjfnIsIGxhYmVsbGVyID0gbGFiZWxsZXIoZGMgPSBjKCIxIiA9ICIxMDAlIiwgIjAuOCIgPSAiODAlIiwgIjAuNiIgPSAiNjAlIiwgIjAuNCIgPSAiNDAlIiwgIjAuMiIgPSAiQ28tdHJucyAyMCUiKSwgciA9IGMoIjAiID0gIlJpYm8gcHJvdCBpbmR4ICA9ICAwIiwgIjAuMSIgPSAiMC4xIiwgIjAuNCIgPSAiMC40IiwgIjEiID0gIjEiKSwgbGFiZWxfcGFyc2VkKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICApICsKICAgICAgbGFicyh4ID0gJ1Byb3BvcnRpb25zIG9mIG1STkFzIHVuZGVyZ29pbmcgQ01EIGZvciBhbGwgZ2VuZXMnLAogICAgICAgICAgIHkgPSAnUmVsYXRpdmUgbWVhbiB0cmFuc2xhdGlvbiBlZmZpY2llbmNpZXMnKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICAgICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC4yLCBsYWJlbC55Lm5wYyA9IDAuNCwgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeF9sb2cxMCgpICsKICAgICAgc2NhbGVfeV9sb2cxMCgpCgpmaWd1cmVTOQp3cml0ZV9yZHMoZmlndXJlUzksICIuLi9maWd1cmVzL2ZpZ3VyZVM5LnJkcyIpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBPUkYgIT0gIllHUjE2OUMtQSIsIE9SRiAhPSAiWUxSMTA2QyIsIE9SRiAhPSAiWUNSMDI0Qy1CIiwgLCByPT0wfHI9PTEsIGRjPT0wLjJ8ZGM9PTEpICU+JQogICNzZWxlY3QoUk1URSwgTVRULCBNTURQLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTU1EUikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gTU1EUCwgeSA9IFJNVEUpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlciA9IGxhYmVsbGVyKGRjID0gYygiMSIgPSAiMTAwJSIsICIwLjgiID0gIjgwJSIsICIwLjYiID0gIjYwJSIsICIwLjQiID0gIjQwJSIsICIwLjIiID0gIkNvLXRybnMgMjAlIiksIHIgPSBjKCIwIiA9ICJSaWJvIHByb3QgaW5keCAgPSAgMCIsICIwLjEiID0gIjAuMSIsICIwLjQiID0gIjAuNCIsICIxIiA9ICIxIiksIGxhYmVsX3BhcnNlZCkpICsKICB0aGVtZV9idygpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICAgKSArCiAgICAgIGxhYnMoeCA9ICdQcm9wb3J0aW9ucyBvZiBtUk5BcyB1bmRlcmdvaW5nIENNRCBmb3IgYWxsIGdlbmVzJywKICAgICAgICAgICB5ID0gJ1JlbGF0aXZlIG1lYW4gdHJhbnNsYXRpb24gZWZmaWNpZW5jaWVzJykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgICAgIHN0YXRfY29yKGFlcyhsYWJlbCA9IHBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMiwgbGFiZWwueS5ucGMgPSAwLjQsIHNpemUgPSA1KSArCiAgICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICAgIHNjYWxlX3lfbG9nMTAoKQpgYGAKCkZpZy4gUzEwCmBgYHtyIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSAxMH0KZmlndXJlUzEwIDwtIGFsbFNpbUlucHV0T3V0cHV0ICU+JQogIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgT1JGICE9ICJZR1IxNjlDLUEiLCBPUkYgIT0gIllMUjEwNkMiLCBPUkYgIT0gIllDUjAyNEMtQiIpICU+JQogICNzZWxlY3QoUk1URSwgTVRULCBNTURQLCBnZW5lTGVuZ3RoX2NvZG9uLCBSTU1EUikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gUk1NRFIsIHkgPSBSTVRFKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogIGZhY2V0X2dyaWQoZGN+ciwgbGFiZWxsZXIgPSBsYWJlbGxlcihkYyA9IGMoIjEiID0gIjEwMCUiLCAiMC44IiA9ICI4MCUiLCAiMC42IiA9ICI2MCUiLCAiMC40IiA9ICI0MCUiLCAiMC4yIiA9ICIyMCUiLCAiMCIgPSAiQ28tdHJucyAwJSIpLCByID0gYygiMCIgPSAiUmlibyBwcm90IGluZHggID0gIDAiLCAiMC4xIiA9ICIwLjEiLCAiMC40IiA9ICIwLjQiLCAiMSIgPSAiMSIpLCBsYWJlbF9wYXJzZWQpKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkKICAgICkgKwogICAgICBsYWJzKHggPSAnUmVsYXRpdmUgbVJOQSBkZWNheSByYXRlcycsCiAgICAgICAgICAgeSA9ICdSZWxhdGl2ZSBtZWFuIHRyYW5zbGF0aW9uIGVmZmljaWVuY2llcycpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogICAgICBzdGF0X2NvcihhZXMobGFiZWwgPSBwYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjIsIGxhYmVsLnkubnBjID0gMC40LCBzaXplID0gNSkgKwogICAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgICBzY2FsZV95X2xvZzEwKCkKCmZpZ3VyZVMxMAp3cml0ZV9yZHMoZmlndXJlUzEwLCAiLi4vZmlndXJlcy9maWd1cmVTMTAucmRzIikKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgphbGxTaW1JbnB1dE91dHB1dCAlPiUKICBmaWx0ZXIocGFyYUNvbWJvICE9ICJtUk5BY29uc3RhbnQiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwLCBPUkYgIT0gIllFUjA1M0MtQSIsIE9SRiAhPSAiWUdSMTY5Qy1BIiwgT1JGICE9ICJZTFIxMDZDIiwgT1JGICE9ICJZQ1IwMjRDLUIiLCByPT0wfHI9PTEsIGRjPT0wfGRjPT0xKSAlPiUKICAjc2VsZWN0KFJNVEUsIE1UVCwgTU1EUCwgZ2VuZUxlbmd0aF9jb2RvbiwgUk1NRFIpICU+JQogIGdncGxvdChhZXMoeCA9IFJNTURSLCB5ID0gUk1URSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICBmYWNldF9ncmlkKGRjfnIsIGxhYmVsbGVyID0gbGFiZWxsZXIoZGMgPSBjKCIxIiA9ICIxMDAlIiwgIjAuOCIgPSAiODAlIiwgIjAuNiIgPSAiNjAlIiwgIjAuNCIgPSAiNDAlIiwgIjAuMiIgPSAiMjAlIiwgIjAiID0gIkNvLXRybnMgMCUiKSwgciA9IGMoIjAiID0gIlJpYm8gcHJvdCBpbmR4ICA9ICAwIiwgIjAuMSIgPSAiMC4xIiwgIjAuNCIgPSAiMC40IiwgIjEiID0gIjEiKSwgbGFiZWxfcGFyc2VkKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgICApICsKICAgICAgbGFicyh4ID0gJ1JlbGF0aXZlIG1STkEgZGVjYXkgcmF0ZXMnLAogICAgICAgICAgIHkgPSAnUmVsYXRpdmUgbWVhbiB0cmFuc2xhdGlvbiBlZmZpY2llbmNpZXMnKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICAgICAgc3RhdF9jb3IoYWVzKGxhYmVsID0gcGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC4yLCBsYWJlbC55Lm5wYyA9IDAuNCwgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeF9sb2cxMCgpICsKICAgICAgc2NhbGVfeV9sb2cxMCgpCmBgYAoKCndhcyBGaWcuIFM5LCBtYXliZSBzaG91bGQgbm90IHVzZSBpdCBjb3ogdGhlIHZsaW5lIGNhbGN1bGF0ZWQgZnJvbSBpdHMgaW5wdXQgZGVjYXkgcmF0ZSBtYXkgbm90IGJlIGFjY3VyYXRlLgpgYGB7cn0KbGlmZXRpbWVEaXN0cmk8LSBmdW5jdGlvbihnZW5ldmVjKXsKICAgIGRmcGxvdCA8LSBjYmluZChkYy5yLmRmW2MoMjo1LCAyMjoyNSksIF0sIGRhdGEuZnJhbWUobWF0cml4KE5BLCBuY29sID0gNTAwMCwgbnJvdyA9IDgqMykpKSAlPiUKICAgICAgICBtdXRhdGUoT1JGID0gYyhyZXAoZ2VuZXZlY1sxXSwgOCksIHJlcChnZW5ldmVjWzJdLCA4KSwgcmVwKGdlbmV2ZWNbM10sIDgpKSkgJT4lCiAgICAgICAgcmVsb2NhdGUoT1JGKQogICAgCiAgICBmb3IoaSBpbiAxOjgpe2RmcGxvdFtpLCA2OjUwMDVdID0gYXMudmVjdG9yKGg1cmVhZChzaW1PdXRwdXRINSwgcGFzdGUwKGdlbmV2ZWNbMV0sICIvbVJOQV9saWZlVGltZXMvIiwgZGZwbG90JHBhcmFDb21ib1tpXSkpKX0KICAgIGZvcihpIGluIDk6MTYpe2RmcGxvdFtpLCA2OjUwMDVdID0gYXMudmVjdG9yKGg1cmVhZChzaW1PdXRwdXRINSwgcGFzdGUwKGdlbmV2ZWNbMl0sICIvbVJOQV9saWZlVGltZXMvIiwgZGZwbG90JHBhcmFDb21ib1tpXSkpKX0KICAgIGZvcihpIGluIDE3OjI0KXtkZnBsb3RbaSwgNjo1MDA1XSA9IGFzLnZlY3RvcihoNXJlYWQoc2ltT3V0cHV0SDUsIHBhc3RlMChnZW5ldmVjWzNdLCAiL21STkFfbGlmZVRpbWVzLyIsIGRmcGxvdCRwYXJhQ29tYm9baV0pKSl9CiAgICAKICAgIGRmcGxvdCAlPiUKICAgICAgICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAidmFyeWluZ1BhcmFDb21ibyIsIHZhbHVlc190byA9ICJsaWZlVGltZXMiLCBjb2xzID0gNjo1MDA1KSAlPiUKICAgICAgICBnZ3Bsb3QoYWVzKGxpZmVUaW1lcywgZmlsbCA9IGRjKSkgKwogICAgICAgIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSwgY29sb3IgPSBOQSkgKwogICAgICAgIGZhY2V0X2dyaWQoZmFjdG9yKE9SRiwgbGV2ZWxzID0gZ2VuZXZlYyl+ciwgCiAgICAgICAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsbGVyKHIgPSBjKCIwIiA9ICJSaWJvIHByb3QgaW5kZXggMCIsICIwLjEiID0gIjAuMSIsICIwLjQiID0gIjAuNCIsICIxIiA9ICIxIikpKSArCiAgICAgICAgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmNvbW1hX2Zvcm1hdChhY2N1cmFjeSA9IDFMKSkgKwogICAgICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDTUQgbGV2ZWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiMCIgPSAiMCIsICIwLjIiID0gIjIwJSIsICIwLjYiID0gIjYwJSIsICIxIiA9ICIxMDAlIikpICsKICAgICAgICB0aGVtZV9idygpICsKICAgICAgICBsYWJzKHggPSBwYXN0ZTAoIm1STkEgbGlmZSB0aW1lIGRpc3RyaWJ1dGlvbiAobG9nMTApIikpICsKICAgICAgICB0aGVtZSgKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICsKICAgICAgICBnZW9tX3ZsaW5lKGRhdGEgPSBmaWx0ZXIoZGZwbG90LCBPUkYgPT0gZ2VuZXZlY1sxXSksIGFlcyh4aW50ZXJjZXB0ID0gMS9zaW1JbnB1dEZlYXR1cmVzJG1STkFEZWNSYXRlTmV5bW90aW5fc2VjW3doaWNoKHNpbUlucHV0RmVhdHVyZXMkT1JGID09IGdlbmV2ZWNbMV0pXSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImRhcmsgZ3JleSIpICsgIzEwNDkuODU2ID0xL3NpbUlucHV0RmVhdHVyZXMkbVJOQURlY1JhdGVOZXltb3Rpbl9zZWNbMV0gIyAxMDQ5Ljg1NiBpcyB0aGUgaW5wdXQgbGlmZXRpbWUgZm9yIFlBTDAwMUMgCiAgICAgICAgZ2VvbV92bGluZShkYXRhID0gZmlsdGVyKGRmcGxvdCwgT1JGID09IGdlbmV2ZWNbMl0pLCBhZXMoeGludGVyY2VwdCA9IDEvc2ltSW5wdXRGZWF0dXJlcyRtUk5BRGVjUmF0ZU5leW1vdGluX3NlY1t3aGljaChzaW1JbnB1dEZlYXR1cmVzJE9SRiA9PSBnZW5ldmVjWzJdKV0pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJkYXJrIGdyZXkiKSArCiAgICAgICAgZ2VvbV92bGluZShkYXRhID0gZmlsdGVyKGRmcGxvdCwgT1JGID09IGdlbmV2ZWNbM10pLCBhZXMoeGludGVyY2VwdCA9IDEvc2ltSW5wdXRGZWF0dXJlcyRtUk5BRGVjUmF0ZU5leW1vdGluX3NlY1t3aGljaChzaW1JbnB1dEZlYXR1cmVzJE9SRiA9PSBnZW5ldmVjWzNdKV0pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJkYXJrIGdyZXkiKSAKICAgICAgICAjIHRoZSBhYm92ZSBsaW5lcyBhcmUgdGhlIGF2ZXJhZ2UgbGlmZSB0aW1lIGNhbGN1bGF0ZWQgZnJvbSBpbnB1dCBkZWNheSByYXRlcwp9CgpsaWZldGltZURpc3RyaShjKCJZQUwwMDFDIiwgIllLUjA3NUMiLCAiWUJSMDExQyIpKQpsaWZldGltZURpc3RyaShjKCJZTFIxMDZDIiwgIllLUjA1NEMiLCAiWUhSMDk5VyIpKSAjIGxvbmdlc3QgZ2VuZXMKbGlmZXRpbWVEaXN0cmkoYygiWUFSMDAyQy1BIiwgIllCTDA1MFciLCAiWUJSMDAzVyIpKQoKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoPTEyfQphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzBfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgbVJOQWFidW5kYW5jZT4xLCBPUkYhPSJZRVIwNTNDLUEiLCBPUkYhPSJZTFIxMDZDIikgJT4lICAjcmVtb3ZlIHRoZSBnZW5lIHdpdGggSEw9NDUwbWluLCBhbHNvIGFuIG91dGxpZXIgZ2VuZSAiWUxSMTA2QyIgd2l0aCBSTVRFPT0wLjYKICAgIHNlbGVjdChPUkYsIHBhcmFDb21ibywgUk1URSwgbVJOQWFidW5kYW5jZV9sb2cxMCwgaW5pUHJvYl9sb2cxMCwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWNfbG9nMTAsIENBSSwgZ2VuZUxlbmd0aF9jb2Rvbl9sb2cxMCkgJT4lCiAgICBgY29sbmFtZXM8LWAoYygiT1JGIiwgInBhcmFDb21ibyIsICJSTVRFIiwgImxvZyhtUk5BYWJ1bmRhbmNlKSIsICJsb2coSW5pUHJvYikiLCAibG9nKERlY1JhdGUpIiwgIkNBSSIsICJsb2coTGVuZ3RoKSIpKSAlPiUKICAgIHBpdm90X2xvbmdlcihjb2xzID0gLWMoUk1URSwgcGFyYUNvbWJvLCBPUkYpLCBuYW1lc190byA9ICJmZWF0dXJlIiwgdmFsdWVzX3RvID0gImZlYXR1cmVWYWwiKSAlPiUKICAgIGdncGxvdChhZXMoeD1mZWF0dXJlVmFsLCB5PVJNVEUsIGNvbG9yPXBhcmFDb21ibykpICsKICAgIGdlb21fcG9pbnQoc2l6ZT0wLjUpICsKICAgIGZhY2V0X3dyYXAofmZlYXR1cmUsIHNjYWxlcyA9ICJmcmVlIiwgbnJvdz0xLCBzdHJpcC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgICB0aGVtZV9idygpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT1yZWwoMS4yKSksICAjIGNhbid0IHVzZSBlbGVtZW50X2JsYW5rKCkgaGVyZSBiZWNhdXNlIGl0IGdpdmVzIGVycm9yIHdoZW4gcDErcDIKICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyID0gMCwgdW5pdCA9ICJwdCIpLAogICAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgIAogICAgICAgICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiAgICAgI3RvIHB1dCB0aGUgc3RyaXAgbGFiZWxzIGJlbG93IHgtYXhpcwogICAgICApICsKICAgICAgICBsYWJzKHggPSAiIiwKICAgICAgICAgICAgIHkgPSAiUmVsYXRpdmUgbWVhbiB0cmFuc2xhdGlvbiBlZmZpY2llbmN5IiwKICAgICAgICAgICAgIHRpdGxlID0gImRjXzBfcl8wIikgKwogICAgICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSArCiAgICAgICAgc3RhdF9jb3IoYWVzKGxhYmVsPXBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMywgbGFiZWwueS5ucGMgPSAwLjIsIHNpemU9NSkgKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLCBsYWJlbHM9YygiIiksIHZhbHVlcyA9IGMoImRjXzFfcl8wIiA9ICIjMUY3OEI0IikpCgoKCmFsbFNpbUlucHV0T3V0cHV0ICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMF9yXzEiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwLCBtUk5BYWJ1bmRhbmNlPjEsIE9SRiE9IllFUjA1M0MtQSIsIE9SRiE9IllMUjEwNkMiKSAlPiUgICNyZW1vdmUgdGhlIGdlbmUgd2l0aCBITD00NTBtaW4sIGFsc28gYW4gb3V0bGllciBnZW5lICJZTFIxMDZDIiB3aXRoIFJNVEU9PTAuNgogICAgc2VsZWN0KE9SRiwgcGFyYUNvbWJvLCBSTVRFLCBtUk5BYWJ1bmRhbmNlX2xvZzEwLCBpbmlQcm9iX2xvZzEwLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlY19sb2cxMCwgQ0FJLCBnZW5lTGVuZ3RoX2NvZG9uX2xvZzEwKSAlPiUKICAgIGBjb2xuYW1lczwtYChjKCJPUkYiLCAicGFyYUNvbWJvIiwgIlJNVEUiLCAibG9nKG1STkFhYnVuZGFuY2UpIiwgImxvZyhJbmlQcm9iKSIsICJsb2coRGVjUmF0ZSkiLCAiQ0FJIiwgImxvZyhMZW5ndGgpIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYyhSTVRFLCBwYXJhQ29tYm8sIE9SRiksIG5hbWVzX3RvID0gImZlYXR1cmUiLCB2YWx1ZXNfdG8gPSAiZmVhdHVyZVZhbCIpICU+JQogICAgZ2dwbG90KGFlcyh4PWZlYXR1cmVWYWwsIHk9Uk1URSwgY29sb3I9cGFyYUNvbWJvKSkgKwogICAgZ2VvbV9wb2ludChzaXplPTAuNSkgKwogICAgZmFjZXRfd3JhcCh+ZmVhdHVyZSwgc2NhbGVzID0gImZyZWUiLCBucm93PTEsIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPXJlbCgxLjIpKSwgICMgY2FuJ3QgdXNlIGVsZW1lbnRfYmxhbmsoKSBoZXJlIGJlY2F1c2UgaXQgZ2l2ZXMgZXJyb3Igd2hlbiBwMStwMgogICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHIgPSAwLCB1bml0ID0gInB0IiksCiAgICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAgCiAgICAgICAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiICAgICAjdG8gcHV0IHRoZSBzdHJpcCBsYWJlbHMgYmVsb3cgeC1heGlzCiAgICAgICkgKwogICAgICAgIGxhYnMoeCA9ICIiLAogICAgICAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIHRyYW5zbGF0aW9uIGVmZmljaWVuY3kiLAogICAgICAgICAgICAgdGl0bGUgPSAiZGNfMF9yXzEiKSArCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgICAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sICBzZXAgPSAifmAsYH4iKSksIGxhYmVsLngubnBjID0gMC4zLCBsYWJlbC55Lm5wYyA9IDAuMiwgc2l6ZT01KSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsIGxhYmVscz1jKCIiKSwgdmFsdWVzID0gYygiZGNfMV9yXzAiID0gIiMxRjc4QjQiKSkKCgoKYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18xX3JfMSIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIG1STkFhYnVuZGFuY2U+MSwgT1JGIT0iWUVSMDUzQy1BIiwgT1JGIT0iWUxSMTA2QyIpICU+JSAgI3JlbW92ZSB0aGUgZ2VuZSB3aXRoIEhMPTQ1MG1pbiwgYWxzbyBhbiBvdXRsaWVyIGdlbmUgIllMUjEwNkMiIHdpdGggUk1URT09MC42CiAgICBzZWxlY3QoT1JGLCBwYXJhQ29tYm8sIFJNVEUsIG1STkFhYnVuZGFuY2VfbG9nMTAsIGluaVByb2JfbG9nMTAsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjX2xvZzEwLCBDQUksIGdlbmVMZW5ndGhfY29kb25fbG9nMTApICU+JQogICAgYGNvbG5hbWVzPC1gKGMoIk9SRiIsICJwYXJhQ29tYm8iLCAiUk1URSIsICJsb2cobVJOQWFidW5kYW5jZSkiLCAibG9nKEluaVByb2IpIiwgImxvZyhEZWNSYXRlKSIsICJDQUkiLCAibG9nKExlbmd0aCkiKSkgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC1jKFJNVEUsIHBhcmFDb21ibywgT1JGKSwgbmFtZXNfdG8gPSAiZmVhdHVyZSIsIHZhbHVlc190byA9ICJmZWF0dXJlVmFsIikgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9ZmVhdHVyZVZhbCwgeT1STVRFLCBjb2xvcj1wYXJhQ29tYm8pKSArCiAgICBnZW9tX3BvaW50KHNpemU9MC41KSArCiAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3c9MSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgdGhlbWVfYncoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9cmVsKDEuMikpLCAgIyBjYW4ndCB1c2UgZWxlbWVudF9ibGFuaygpIGhlcmUgYmVjYXVzZSBpdCBnaXZlcyBlcnJvciB3aGVuIHAxK3AyCiAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDAsIHVuaXQgPSAicHQiKSwKICAgICAgICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAKICAgICAgICAgICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIgICAgICN0byBwdXQgdGhlIHN0cmlwIGxhYmVscyBiZWxvdyB4LWF4aXMKICAgICAgKSArCiAgICAgICAgbGFicyh4ID0gIiIsCiAgICAgICAgICAgICB5ID0gIlJlbGF0aXZlIG1lYW4gdHJhbnNsYXRpb24gZWZmaWNpZW5jeSIsCiAgICAgICAgICAgICB0aXRsZSA9ICJkY18xX3JfMSIpICsKICAgICAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikgKwogICAgICAgIHN0YXRfY29yKGFlcyhsYWJlbD1wYXN0ZSguLnIubGFiZWwuLiwgIHNlcCA9ICJ+YCxgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjMsIGxhYmVsLnkubnBjID0gMC4yLCBzaXplPTUpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0iIiwgbGFiZWxzPWMoIiIpLCB2YWx1ZXMgPSBjKCJkY18xX3JfMCIgPSAiIzFGNzhCNCIpKQoKCmBgYAoKCgoKYGBge3J9CnRtcGRmIDwtIGRhdGEuZnJhbWUobGlmZXRpbWUgPSBsb2cxMChhcy5udW1lcmljKGRmcGxvdFsxLCA2OjUwMDVdKSkpCndoaWNoLm1heChkZW5zaXR5KHRtcGRmJGxpZmV0aW1lKSR5KQpkZW5zaXR5KHRtcGRmJGxpZmV0aW1lKSR4WzM4N10KZ2dwbG90KHRtcGRmLCBhZXMobGlmZXRpbWUpKSArIGdlb21fZGVuc2l0eSgpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gZGVuc2l0eSh0bXBkZiRsaWZldGltZSkkeFszODddKSAKCgpgYGAKCgpGaWcuIFMKCk5PVEVTOiAKT3V0cHV0IGRlY2F5IHJhdGUgPSAxL21lYW4gbGlmZXRpbWUgPGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhcnRpY2xlX2RlY2F5PgoKVG90YWwgb3V0cHV0IGRlY2F5IHJhdGUgPSBvdXRwdXQgZGVjYXkgcmF0ZSAqIG91dHB1dCBtZWFuIG1STkEgY291bnQKClRvdGFsIGlucHV0IGRlY2F5IHJhdGUgPSBpbnB1dCBkZWNheSByYXRlICogbVJOQWFidW5kYW5jZQoKVG90YWwgc3ludGhlc2lzIHJhdGUgPSBhIHNjYWxlZCBjb25zdGFudAoKKFRoZSBhYm92ZSByYXRlcyBhcmUgYWxsIGdlbmUtc3BlY2lmaWMpCgpTdW1tYXJ5OiBjaGFuZ2luZyB0b3RhbCBvdXRwdXQgZGVjYXkgcmF0ZSBpcyBhIHJlc3VsdCBvZiBjaGFuZ2luZyBjby10cmFuc2xhdGlvbmFsIGRlY2F5IGFuZCByaWJvc29tZSBwcm90ZWN0aW9uLiBJbiBvcmRlciB0byBtYWludGFpbiB0aGUgY29uc3RhbnQgbVJOQSBsZXZlbCwgd2UgaGF2ZSB0byBzY2FsZSB0aGUgdG90YWwgc3ludGhlc2lzIHJhdGVzIHRvIGNvdW50ZXItZWZmZWN0IHRoZSBjaGFuZ2luZyBvdXRwdXQgZGVjYXkgcmF0ZXMuCgpXaGVuIGNvLXRyYW5zbGF0aW9uYWwgZGVjYXkgaXMgaGlnaGVyIHRoYW4gMCwgdGhlcmUncyBhbHdheXMgYSBzdXJwbHVzIG9mIG1STkFzIG1hcmtlZCBmb3IgZGVjYXksIHRoYXQgYXJlIG5vdCBhY2NvdW50ZWQgd2hlbiBjYWxjdWxhdGluZyB0b3RhbCBkZWNheSBwcm9iYWJpbGl0aWVzIChUaGV5J3JlIG5vdCBhY2NvdW50ZWQgYmVjYXVzZSB0aGV5IGFscmVhZHkgaGF2ZSBkZWNheSBtYWNoaW5lcnkgYm91bmQgdG8gdGhlbSwgc28gY2Fubm90IGJlIGFjY291bnRlZCBhZ2FpbiBpbnRvIHRoZSBtUk5BIHBvb2wgdGhhdCBjYW4gc3RpbGwgYmUgZGVncmFkZWQpLiBUaGVyZWZvcmUgdGhlIHN5bnRoZXNpcyByYXRlcyBhcmUgc2NhbGVkLCBpbiBvcmRlciB0byBtYWludGFpbiBhIHN0YWJsZSByZWxhdGl2ZSBtUk5BIGNvdW50ICg9IG1lYW4gb3V0cHV0IG1STkEgY291bnQvbVJOQWFidW5kYW5jZSkgZm9yIGl0IHRvIGJlIGNsb3NlIHRvIDEgKFN1cHAgRmlnIDEpLiBUaGUgbWVhbiBvdXRwdXQgbVJOQSBjb3VudCBmb3IgZWFjaCBnZW5lIGlzIGEgcmVzdWx0IG9mIHRoZSBiYWxhbmNlIGJldHdlZW4gaXRzIHNjYWxlZCBzeW50aGVzaXMgcmF0ZSBhbmQgdG90YWwgb3V0cHV0IGRlY2F5IHJhdGUuIEluIG90aGVyIHdvcmRzLCB0aGUgdG90YWwgb3V0cHV0IGRlY2F5IHJhdGUgZGlyZWN0bHkgcmVzcG9uZCB0byB0aGUgc2NhbGVkIHN5bnRoZXNpcyByYXRlLCByYXRoZXIgdGhhbiB0aGUgaW5wdXQgZGVjYXkgcmF0ZS4gCgpUaGUgc2NhbGVkIHRvdGFsIHN5bnRoZXNpcyByYXRlcyBhcmUgdGhlIHNtYWxsZXN0IHdoZW4gY28tdHJhbnNsYXRpb25hbCBkZWNheSA9IDEwMCUsIHNvIHRoYXQgdGhlIHRvdGFsIHJlYWwtdGltZSBtUk5BIGNvdW50IGNhbiBiZSBjbG9zZSB0byBtUk5BYWJ1bmRhbmNlIGV2ZW4gd2l0aCB0aGUgaGlnaGVzdCBhbW91bnQgb2YgbVJOQXMgbWFya2VkIGZvciBkZWNheS4gSW4gY29udHJhc3QsIHRoZSBzY2FsZWQgdG90YWwgc3ludGhlc2lzIHJhdGVzIGFyZSB0aGUgbGFyZ2VzdCBhbmQgZXF1YWwgdG8gdGhlIHRvdGFsIGlucHV0IGRlY2F5IHJhdGVzIHdoZW4gY28tdHJhbnMgZGVjYXkgPSAwJSAoU3VwcCBGaWcgMmEpLCBiZWNhdXNlIHRoZXJlIGlzIDAgbVJOQSBtYXJrZWQgZm9yIGRlY2F5LiAKCkh5cG90aGV0aWNhbGx5LCB0aGUgdG90YWwgb3V0cHV0IGRlY2F5IHJhdGVzIHNob3VsZCBlcXVhbCB0byB0aGUgdG90YWwgc3ludGhlc2lzIHJhdGVzIGluIG9yZGVyIHRvIG1haW50YWluIHRoZSByZWFsLXRpbWUgbVJOQSBjb3VudCB0byBiZSBsYXJnZWx5IHRoZSBzYW1lIGF0IHRoZSBiZWdpbm5pbmcgYW5kIHRoZSBlbmQgb2YgdGhlIHNpbXVsYXRpb24uIElmIHVuZXF1YWwsIHRoZSByZWFsLXRpbWUgbVJOQSBjb3VudCBzaG91bGQgZWl0aGVyIGdvIHVwIG9yIGRvd24gYXMgdGhlIHNpbXVsYXRpb24gY29udGludWVzIGNvbXBhcmVkIHRvIHRoZSBiZWdpbmluZyBhbW91bnQgKGkuZS4gbVJOQWFidW5kYW5jZSkuIEhvd2V2ZXIsIG91ciByZXN1bHRzIHNob3cgdGhhdCB0aGUgdG90YWwgb3V0cHV0IGRlY2F5IHJhdGVzIGFyZSBzbGlnaHRseSBsYXJnZXIgdGhhbiB0aGUgc2NhbGVkIHN5bnRoZXNpcyByYXRlcyBhY3Jvc3MgYWxsIHRoZSBwYXJhbWV0ZXIgY29tYm9zIChTdXBwIEZpZyAyYi4gdGhpcyBpcyB0aGUgcGFydCBJIGRvbid0IHVuZGVyc3RhbmQsIGlzIGl0IGNveiB0aGUgdG90YWwgb3V0cHV0IGRlY2F5IHJhdGVzIGluY2x1ZGUgY29uc2lkZXJpbmcgbVJOQXNNYXJrZWRGb3JEZWNheSwgYnV0IHRoZSB0b3RhbCBzY2FsZWQgc3ludGhlc2lzIHJhdGVzIGRvZXNuJ3QgaW5jbHVkZSBtUk5Bc01hcmtlZEZvckRlY2F5KSwgYW5kIHRoYXQncyBzb21laG93IGNvbnRyaWJ1dGluZyB0byB0aGUgbWVhbiByZWFsLXRpbWUgbVJOQSBjb3VudCBiZWluZyBlcXVhbCB0byBtUk5BYWJ1bmRhbmNlIGFzIHNob3duIGluIFN1cHAgRmlnIDEuIAoKQmVjYXVzZSB0aGUgb3V0cHV0IGRlY2F5IHJhdGVzIGRpcmVjdGx5IHJlc3BvbmQgdG8gdG90YWwgc3ludGhlc2lzIHJhdGVzLCB0aGV5IGFyZSBpbmZsdWVuY2VkIGJ5IHRoZSBwYXJhIGNvbWJvcyBpbiB0aGUgc2FtZSB3YXkgdGhhdCB0b3RhbCBzeW50aGVzaXMgcmF0ZXMgYXJlLiBUaGF0IGV4cGxhaW5zIHdoeSBTdXBwIEZpZyAyYyBpcyBzaW1pbGFyIHRvIFN1cHAgRmlnIDJhIGluIHRoYXQgdGhlIHBlYWtzIHNrZXcgdG8gdGhlIHJpZ2h0IGFzIGNvLXRyYW5zbGF0aW9uYWwgZGVjYXkgcmF0aW8gZ29lcyBkb3duLiBIb3dldmVyIGluIFN1cHAgRmlnIDJhLCB0aGUgcmF0aW8gKHNjYWxlZCBzeW50aGVzaXMgcmF0ZXMgVi5TLiB0b3RhbCBpbnB1dCBkZWNheSByYXRlcykgc2tld2VkIGZyb20gbGVzcyB0aGFuIDEgdG8gMTsgd2hpbGUgaW4gU3VwcCBGaWcgMmMsIHRoZSByYXRpbyAodG90YWwgb3V0cHV0IGRlY2F5IHJhdGVzIFYuUy4gdG90YWwgaW5wdXQgZGVjYXkgcmF0ZXMpIHNrZXdlZCBmcm9tIDEgdG8gbGFyZ2VyIHRoYW4gMS4gVGhpcyB3b3VsZCBtYWtlIHNlbnNlIGlmIHdlIGNhbiBleHBsYWluIHdoYXQncyBnb2luZyBvbiBpbiBTdXBwIEZpZyAyYi4gCgpNZWFud2hpbGUsIHRoZSBvdXRwdXQgZGVjYXkgcmF0ZXMgZm9yIHNob3J0IGdlbmVzIGFyZSBtdWNoIGxlc3MgYWZmZWN0ZWQgYnkgZGlmZmVyZW50IGNvLXRyYW5zbGF0aW9uYWwgZGVjYXkgcHJvcG9ydGlvbnMgdGhhbiBsb25nIGdlbmVzIChTdXBwIEZpZyAyZCkuIFRoaXMgc2hvdWxkIGJlIGEgcmVmbGVjdGlvbiB0aGF0IHRoZSB0b3RhbCBzeW50aGVzaXMgcmF0ZXMgZm9yIHNob3J0IGdlbmVzIGFyZSBjaGFuZ2luZyBsZXNzIHdpdGggY2hhbmdpbmcgY28tdHJhbnNsYXRpb25hbCBkZWNheS4KClN1cHAgRmlnIDJhOiBUaGUgc2NhbGVkIHN5bnRoZXNpcyByYXRlcyBhcmUgdGhlIHNtYWxsZXN0IHdoZW4gY28tdHJhbnMgZGVjYXkgPSAxMDAlLCB3aGlsZSB0aGV5XG5hcmUgdGhlIGxhcmdlc3QgYW5kIGVxdWFsIHRvIHRoZSB0b3RhbCBpbnB1dCBkZWNheSByYXRlcyB3aGVuIGNvLXRyYW5zIGRlY2F5ID0gMCUgCgpTdXBwIEZpZyAyYjogVG90YWwgb3V0cHV0IG1STkEgZGVjYXkgcmF0ZXMgYXJlIHNsaWdodGx5IGxhcmdlciB0aGFuIHNjYWxlZCBtUk5BIHN5bnRoZXNpcyByYXRlcyBcbiwgYnV0IHRoZSByYXRpbyBzdGF5cyBzdGFibGUgd2l0aCBjaGFuZ2luZyBwYXJhbWV0ZXJzIFxuKEkgZG9uJ3QgdW5kZXJzdGFuZCB3aHkgdGhlIGRlY2F5IHJhdGVzIGhhdmUgdG8gYmUgbGFyZ2VyKQoKU3VwcCBGaWcgMmM6IE91dHB1dCBkZWNheSByYXRlcyByZXNwb25kIHRvIHNjYWxlZCBzeW50aGVzaXMgcmF0ZXMsIHRoZXJlZm9yZSBpdHMgcmF0aW8gYWdhaW5zdCBcbnRvdGFsIGlucHV0IGRlY2F5IHJhdGVzIHNob3dzIHNpbWlsYXIgcGF0dGVyIGFzIHNjYWxlZCBzeW50aGVzaXMgcmF0ZXMgaW4gRmlnIDIKClN1cHAgRmlnIDJkOiBPdXRwdXQgZGVjYXkgcmF0ZXMgZm9yIHNob3J0IGdlbmVzIGFyZSBtdWNoIGxlc3MgYWZmZWN0ZWQgYnkgZGlmZmVyZW50IFxuY28tdHJhbnNsYXRpb25hbCBkZWNheSB0aGFuIGxvbmcgZ2VuZXMKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0KYWxsU2ltSW5wdXRPdXRwdXRfdHJpYWwgPC0gcmVhZF9mZWF0aGVyKCIuLi8uLi8uLi9leHAwL2V4dGVybmFsRGF0YS9leHAxMV9vdXRjb21lQWxsLmZlYXRoZXIiKQp0bXAgPC0gYWxsU2ltSW5wdXRPdXRwdXRfdHJpYWwgJT4lIAogIGZpbHRlcihjb21ibyAhPSAibVJOQWNvbnN0YW50IiwgdyAhPSAwLjAxLCB3ICE9IDAuMDUsIHcgIT0gMC4yKSAlPiUgCiAgc2VsZWN0KE5NTUMsIGNvbWJvLCBPUkYsIHIsIHcpICU+JSAjIE5NTUMgaW4gdHJpYWwgPSBSTU1DIGluIGV4cDAsICJub3JtYWxpemVkIiBWUyAicmVsYXRpdmUiCiAgbXV0YXRlKGRjPTEtYXMubnVtZXJpYyhyKSkgJT4lCiAgc2VsZWN0KC1yKSAlPiUgI2RlbGV0ZSB0aGUgb3JpZ2luYWwgY29sdW1uIG5hbWVkICJyIiwgaW4gdHJpYWwgZGF0YSB0aGUgciBtZWFucyBDTUQgbGV2ZWxzLCBhbmQgdyBtZWFucyByaWJvc29tZSBwcm90ZWN0aW9uIGluZGV4CiAgZHBseXI6OnJlbmFtZSgiciI9InciLCAicGFyYUNvbWJvIj0iY29tYm8iLCAiUk1NQ3RyaWFsIj0iTk1NQyIpICU+JSAjIGNoYW5nZSB0aGUgb3JpZ2luYWwgY29sIG5hbWVkICJ3IiBpbnRvICJyIiwgYi9jICJyIiBpbiBleHAwIG1lYW5zIHJpYm9zb21lIHByb3RlY3Rpb24gaW5kZXgKICBtdXRhdGUocGFyYUNvbWJvPXBhc3RlMCgiZGNfIiwgZGMsICJfcl8iLCByKSkgJT4lCiAgc2VsZWN0KC1kYywgLXIpCiAgCiAgICAKc3VwMSA8LSAoYWxsU2ltSW5wdXRPdXRwdXQgJT4lCiAgICBmaWx0ZXIocGFyYUNvbWJvICE9ICJtUk5BY29uc3RhbnQiKSAlPiUKICAgIGxlZnRfam9pbiguLCB0bXAsIGJ5ID0gYygicGFyYUNvbWJvIj0icGFyYUNvbWJvIiwgIk9SRiI9Ik9SRiIpKSkgJT4lCiAgICBzZWxlY3QoInBhcmFDb21ibyIsICJSTU1DIiwgIlJNTUN0cmlhbCIsICJkYyIsICJyIikgJT4lCiAgICBkcGx5cjo6cmVuYW1lKCJBZnRlclNjYWxpbmciPSJSTU1DIiwgIkJlZm9yZVNjYWxpbmciPSJSTU1DdHJpYWwiKSAlPiUKICAgIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJrZXkiLCB2YWx1ZXNfdG8gPSAiUk1NQ3ZhbHVlIiwgY29scyA9IDI6MykgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9Uk1NQ3ZhbHVlLCBjb2xvcj1rZXkpKSArCiAgICAgICAgZ2VvbV9kZW5zaXR5KCkgKwogICAgICAgIGZhY2V0X2dyaWQoZGN+ciwgbGFiZWxsZXI9bGFiZWxsZXIoZGM9YygiMCI9IjAlIiwgIjAuMiI9IjIwJSIsICIwLjQiPSI0MCUiLCAiMC42Ij0iNjAlIiwgIjAuOCI9IjgwJSIsICIxIj0iQ01EIDEwMCUiKSwgcj1jKCIwIj0iUmlibyBwcm90IGluZHggPSAwIiwgIjAuMSI9IjAuMSIsICIwLjQiPSIwLjQiLCAiMSI9IjEiKSwgbGFiZWxfcGFyc2VkKSkgKyAKICAgICAgICBsYWJzKHRpdGxlID0gIlN1cCBGaWcgMTogbVJOQSBjb3VudHMgd2hlbiB2YXJ5aW5nIGFyZSBsYXJlZ2VseSBlcXVhbCB0byB3aGVuIHRoZXkgYXJlIGNvbnN0YW50IFxuYWZ0ZXIgc2NhbGluZyB0aGUgbVJOQSBzeW50aGVzaXMgcmF0ZXMiLCAKICAgICAgICAgICAgIHg9IlJlbGF0aXZlIG1lYW4gbVJOQSBjb3VudCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoKSArCiAgICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0xLCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3I9ImRhcmsgZ3JleSIpICsKICAgICAgICB0aGVtZV9idygpICsKICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgICAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkgIyBtYWtlIHRoZSBncmlkbGluZSBjb2xvciBkYXJrZXIKCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgcGxvdHRpbmcgdGhlICh0b3RhbCBzeW4gcmF0ZSBhZnRlciBzY2FsaW5nKS8oaW5wdXQgZGVjYXkgcmF0ZSptUk5BYWJ1bmRhbmNlKSBmb3IgYWxsIGdlbmVzIGZvciBhbGwgcncgY29tYm9zCm91dGRmIDwtIHRpYmJsZShtYXRyaXgoTkEsIG5jb2w9bnJvdyhkYy5yLmRmKS0xLCBucm93PTQ4MzkpKQoKZm9yIChpIGluIDE6KG5yb3coZGMuci5kZiktMSkpIAp7CiAgICBpbmYgPC0gcmVhZC50YWJsZShwYXN0ZTAoIi4uLy4uL3NpbXVsYXRpb25zL3NpbUlucHV0L2FsbEdlbmVzRGVjckVxdWFsc1N5bnJXaXRoU2NhbGluZ18iLCBkYy5yLmRmJHBhcmFDb21ib1tpKzFdLCAiX1MuY2VyLm1STkEuaW5pLmFibmRjLnN5bi5kZWMudHN2IikpCiAgICBvdXRkZlssIGldIDwtIGluZlssIDNdLyhpbmZbLCA0XSppbmZbLCAyXSkKfQoKY29sbmFtZXMob3V0ZGYpIDwtIGRjLnIuZGYkcGFyYUNvbWJvWzI6bnJvdyhkYy5yLmRmKV0KCnN1cDJhIDwtIG91dGRmICU+JQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJwYXJhQ29tYm8iLCB2YWx1ZXNfdG8gPSAidmFsdWUiLCBjb2xzID0gMToobnJvdyhkYy5yLmRmKS0xKSkgJT4lCiAgbGVmdF9qb2luKC4sIGRjLnIuZGYsIGJ5ID0gInBhcmFDb21ibyIpICU+JQogIGZpbHRlcih2YWx1ZSAhPSAwLCBwYXJhQ29tYm8gPT0gImRjXzFfcl8wInxwYXJhQ29tYm8gPT0gImRjXzBfcl8wInxwYXJhQ29tYm8gPT0gImRjXzFfcl8xInxwYXJhQ29tYm8gPT0gImRjXzBfcl8xIikgJT4lCiAgZ2dwbG90KGFlcyh4PXZhbHVlKSkgKwogICAgZ2VvbV9kZW5zaXR5KCkgKwogICAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlcj1sYWJlbGxlcihkYz1jKCIwIj0iMCUiLCAiMC4yIj0iMjAlIiwgIjAuNCI9IjQwJSIsICIwLjYiPSI2MCUiLCAiMC44Ij0iODAlIiwgIjEiPSJDTUQgMTAwJSIpLCByPWMoIjAiPSJSaWJvIHByb3QgaW5keCA9IDAiLCAiMC4xIj0iMC4xIiwgIjAuNCI9IjAuNCIsICIxIj0iMSIpLCBsYWJlbF9wYXJzZWQpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPTEsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvcj0iZGFyayBncmV5IikgKwogICAgbGFicyh0aXRsZSA9ICIiLAogICAgICAgICB4PSJTY2FsZWQgc3ludGhlc2lzIHJhdGVzL1RvdGFsIGlucHV0IGRlY2F5IHJhdGVzIikgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT05KSwKICAgICAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMC45LCAxLCAxLjEsIDEuMywgMS41KSkKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgcGxvdHRpbmcgdGhlIChvdXRwdXQgZGVjYXkgcmF0ZSkvKHN5biByYXRlIGFmdGVyIHNjYWxpbmcpIGZvciBhbGwgZ2VuZXMgZm9yIGFsbCBkYy9yIHBhcmFDb21ib3MKbW1kckFsbGdlbmVBbGxkY3IgPC0gcmVhZF9mZWF0aGVyKCIuLi9jYWxjdWxhdGVkTWV0cmljcy9tbWRyQWxsZ2VuZUFsbGRjci5mZWF0aGVyIilbLCAyOm5yb3coZGMuci5kZildCm1tY0FsbGdlbmVBbGxkY3I8LSByZWFkX2ZlYXRoZXIoIi4uL2NhbGN1bGF0ZWRNZXRyaWNzL21tY0FsbGdlbmVBbGxkY3IuZmVhdGhlciIpWywgMjpucm93KGRjLnIuZGYpXQp0b3RkciA8LSBtbWRyQWxsZ2VuZUFsbGRjciptbWNBbGxnZW5lQWxsZGNyCgp0b3RzeW5yIDwtIHRpYmJsZShtYXRyaXgoTkEsIG5jb2w9bnJvdyhkYy5yLmRmKS0xLCBucm93PTQ4MzkpKQpmb3IgKGkgaW4gMToobnJvdyhkYy5yLmRmKS0xKSkKewogICAgaW5mIDwtIHJlYWQudGFibGUocGFzdGUwKCIuLi8uLi9zaW11bGF0aW9ucy9zaW1JbnB1dC9hbGxHZW5lc0RlY3JFcXVhbHNTeW5yV2l0aFNjYWxpbmdfIiwgZGMuci5kZiRwYXJhQ29tYm9baSsxXSwgIl9TLmNlci5tUk5BLmluaS5hYm5kYy5zeW4uZGVjLnRzdiIpKQogICAgdG90c3luclssIGldIDwtIGluZlssIDNdCn0KCnJhdGlvLmRyLnN5bnIgPC0gdG90ZHIvdG90c3lucgpjb2xuYW1lcyhyYXRpby5kci5zeW5yKSA8LSBkYy5yLmRmJHBhcmFDb21ib1syOm5yb3coZGMuci5kZildCnJhdGlvLmRyLnN5bnIgPC0gcmF0aW8uZHIuc3luclstMTI3OCwgXSAgICMgZ2VuZSB3aXRoIHRoZSBITC1taW49NDkwIG1pbiwgdGhlIGRhdGEgcG9pbnQgc2tld3MgdGhlIHNjYWxlCgpzdXAyYiA8LSByYXRpby5kci5zeW5yICU+JQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJwYXJhQ29tYm8iLCB2YWx1ZXNfdG8gPSAidmFsdWUiLCBjb2xzID0gMToobnJvdyhkYy5yLmRmKS0xKSkgJT4lCiAgbGVmdF9qb2luKC4sIGRjLnIuZGYsIGJ5ID0gInBhcmFDb21ibyIpICU+JQogIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wInxwYXJhQ29tYm8gPT0gImRjXzBfcl8wInxwYXJhQ29tYm8gPT0gImRjXzFfcl8xInxwYXJhQ29tYm8gPT0gImRjXzBfcl8xIikgJT4lIAogIGZpbHRlcighaXMubmEodmFsdWUpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFsdWUpKSArCiAgICBnZW9tX2RlbnNpdHkoKSArCiAgICBmYWNldF9ncmlkKGRjfnIsIGxhYmVsbGVyPWxhYmVsbGVyKGRjPWMoIjAiPSIwJSIsICIwLjIiPSIyMCUiLCAiMC40Ij0iNDAlIiwgIjAuNiI9IjYwJSIsICIwLjgiPSI4MCUiLCAiMSI9IkNNRCAxMDAlIiksIHI9YygiMCI9IlJpYm8gcHJvdCBpbmR4ID0gMCIsICIwLjEiPSIwLjEiLCAiMC40Ij0iMC40IiwgIjEiPSIxIiksIGxhYmVsX3BhcnNlZCkpICsKICAgIGxhYnModGl0bGUgPSAiIiwgCiAgICAgICAgIHg9IlRvdGFsIG91dHB1dCBkZWNheSByYXRlcy9TY2FsZWQgc3ludGhlc2lzIHJhdGVzIikgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0xLCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3I9ImRhcmsgZ3JleSIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9OSksCiAgICAgICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT05KSwKICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgcGxvdHRpbmcgdGhlIChvdXRwdXQgZGVjYXkgcmF0ZSpyZWFsIHRpbWUgbVJOQSkvKGlucHV0IGRlY2F5IHJhdGUqbVJOQWFidW5kYW5jZSlmb3IgYWxsIGdlbmVzIGZvciBhbGwgcncgY29tYm9zCm91dGRmIDwtIHRpYmJsZShtYXRyaXgoTkEsIG5jb2w9bnJvdyhkYy5yLmRmKS0xLCBucm93PTQ4MzkpKSAjY29udGFpbnMgYWxsIHRoZSB0b3RhbCBpbnB1dCBkZWNheSByYXRlcwoKZm9yIChpIGluIDE6KG5yb3coZGMuci5kZiktMSkpICAjIHRoZXNlIDE2IGNvbHVtbnMgYXJlIGFsbCB0aGUgc2FtZSwgYWxsIGVxdWFsIHRvIHNpbUlucHV0RmVhdHVyZXMkbVJOQWFidW5kYW5jZSpzaW1JbnB1dEZlYXR1cmVzJG1STkFEZWNSYXRlTmV5bW90aW5fc2VjCnsKICAgIGluZiA8LSByZWFkLnRhYmxlKHBhc3RlMCgiLi4vLi4vc2ltdWxhdGlvbnMvc2ltSW5wdXQvYWxsR2VuZXNEZWNyRXF1YWxzU3lucldpdGhTY2FsaW5nXyIsIGRjLnIuZGYkcGFyYUNvbWJvW2krMV0sICJfUy5jZXIubVJOQS5pbmkuYWJuZGMuc3luLmRlYy50c3YiKSkKICAgIG91dGRmWywgaV0gPC0gKGluZlssIDRdKmluZlssIDJdKQp9CgpvdXRkZiA8LSB0b3Rkci9vdXRkZgpjb2xuYW1lcyhvdXRkZikgPC0gZGMuci5kZiRwYXJhQ29tYm9bMjpucm93KGRjLnIuZGYpXQoKc3VwMmMgPC0gb3V0ZGZbLTEyNzgsIF0gJT4lICAgICAgICMgZ2VuZSB3aXRoIHRoZSBITC1taW49NDkwIG1pbiwgdGhlIGRhdGEgcG9pbnQgc2tld3MgdGhlIHNjYWxlcwogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJwYXJhQ29tYm8iLCB2YWx1ZXNfdG8gPSAidmFsdWUiLCBjb2xzID0gMToobnJvdyhkYy5yLmRmKS0xKSkgJT4lCiAgbGVmdF9qb2luKC4sIGRjLnIuZGYsIGJ5ID0gInBhcmFDb21ibyIpICU+JQogIGZpbHRlcih2YWx1ZSAhPSAwLCBwYXJhQ29tYm8gPT0gImRjXzFfcl8wInxwYXJhQ29tYm8gPT0gImRjXzBfcl8wInxwYXJhQ29tYm8gPT0gImRjXzFfcl8xInxwYXJhQ29tYm8gPT0gImRjXzBfcl8xIikgJT4lCiAgZ2dwbG90KGFlcyh4PXZhbHVlKSkgKwogICAgZ2VvbV9kZW5zaXR5KCkgKwogICAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlcj1sYWJlbGxlcihkYz1jKCIwIj0iMCUiLCAiMC4yIj0iMjAlIiwgIjAuNCI9IjQwJSIsICIwLjYiPSI2MCUiLCAiMC44Ij0iODAlIiwgIjEiPSJDTUQgMTAwJSIpLCByPWMoIjAiPSJSaWJvIHByb3QgaW5keCA9IDAiLCAiMC4xIj0iMC4xIiwgIjAuNCI9IjAuNCIsICIxIj0iMSIpLCBsYWJlbF9wYXJzZWQpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPTEsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvcj0iZGFyayBncmV5IikgKwogICAgbGFicyh0aXRsZSA9ICIiLAogICAgICAgICB4PSJUb3RhbCBvdXRwdXQgZGVjYXkgcmF0ZXMvVG90YWwgaW5wdXQgZGVjYXkgcmF0ZXMiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKCNzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT04KSwKICAgICAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgICMgaGlkZSB0aGUgZ3JpZCB0aXRsZQoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgc2wgPSBzaG9ydCBvciBsb25nCm91dGRmJHNsIDwtIHJlcChOQSw0ODM5KSAgIApvdXRkZiRzbFt3aGljaChzaW1JbnB1dEZlYXR1cmVzJGdlbmVMZW5ndGhfY29kb24+NTEyKV0gPC0gIkxvbmciCm91dGRmJHNsW3doaWNoKHNpbUlucHV0RmVhdHVyZXMkZ2VuZUxlbmd0aF9jb2Rvbjw9NTEyKV0gPC0gIlNob3J0IgoKCnN1cDJkIDwtIG91dGRmWy0xMjc4LCBdICU+JSAgICAgICAjIHRvb2sgdGhlIGdlbmUgd2l0aCB0aGUgSEwtbWluPTQ5MCBtaW4sIHRoZSBkYXRhIHBvaW50IHNrZXdzIHRoZSBzY2FsZXMKICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAicGFyYUNvbWJvIiwgdmFsdWVzX3RvID0gInZhbHVlIiwgY29scyA9IDE6KG5yb3coZGMuci5kZiktMSkpICU+JQogIGxlZnRfam9pbiguLCBkYy5yLmRmLCBieSA9ICJwYXJhQ29tYm8iKSAlPiUKICBmaWx0ZXIodmFsdWUgIT0gMCwgcGFyYUNvbWJvID09ICJkY18xX3JfMCJ8cGFyYUNvbWJvID09ICJkY18wX3JfMCJ8cGFyYUNvbWJvID09ICJkY18xX3JfMSJ8cGFyYUNvbWJvID09ICJkY18wX3JfMSIpICU+JQogIGdncGxvdChhZXMoeD12YWx1ZSwgY29sb3I9c2wsIGdyb3VwPXNsKSkgKwogICAgZ2VvbV9kZW5zaXR5KCkgKwogICAgZmFjZXRfZ3JpZChkY35yLCBsYWJlbGxlcj1sYWJlbGxlcihkYz1jKCIwIj0iMCUiLCAiMC4yIj0iMjAlIiwgIjAuNCI9IjQwJSIsICIwLjYiPSI2MCUiLCAiMC44Ij0iODAlIiwgIjEiPSJDTUQgMTAwJSIpLCByPWMoIjAiPSJSaWJvIHByb3QgaW5keCA9IDAiLCAiMC4xIj0iMC4xIiwgIjAuNCI9IjAuNCIsICIxIj0iMSIpLCBsYWJlbF9wYXJzZWQpKSArCiAgICBsYWJzKHRpdGxlID0gIiIsCiAgICAgICAgIHg9IlRvdGFsIG91dHB1dCBkZWNheSByYXRlcy9Ub3RhbCBpbnB1dCBkZWNheSByYXRlcyIpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9MSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSJkYXJrIGdyZXkiKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKAogICAgICAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9OSksCiAgICAgICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuOSwgMC45NSksCiAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBsZWdlbmQuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksICMgY2hhbmdlIHRoZSBsZWdlbmQgYmFja2dyb3VuZCB0byB0cmFuc3BhcmVudAogICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lIikpICsKICAgIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiIiwgbGFiZWxzID0gKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpzdXAxCgpzdXAyIDwtIChzdXAyYXxzdXAyYikvKHN1cDJjfHN1cDJkKQpzdXAyICsgcGxvdF9hbm5vdGF0aW9uKAogICB0aXRsZSA9ICdTdXBwIEZpZyAyLicsCiAgIyBzdWJ0aXRsZSA9ICdTdXBwIEZpZyAyLicsCiAgIyBjYXB0aW9uID0gJ0hlbGxvJywgICAjIHRoaXMgb25lIGFwcGVhcnMgYXQgdGhlIGJvdHRvbQogIHRhZ19sZXZlbHMgPSAnYScKKQoKCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnRvdC5pbi5kciA8LSB0aWJibGUobWF0cml4KE5BLCBuY29sPW5yb3coZGMuci5kZiktMSwgbnJvdz00ODM5KSkgI2NvbnRhaW5zIGFsbCB0aGUgdG90YWwgaW5wdXQgZGVjYXkgcmF0ZXMKCmZvciAoaSBpbiAxOihucm93KGRjLnIuZGYpLTEpKSAgIyB0aGVzZSAxNiBjb2x1bW5zIGFyZSBhbGwgdGhlIHNhbWUsIGFsbCBlcXVhbCB0byBzaW1JbnB1dEZlYXR1cmVzJG1STkFhYnVuZGFuY2Uqc2ltSW5wdXRGZWF0dXJlcyRtUk5BRGVjUmF0ZU5leW1vdGluX3NlYwp7CiAgICBpbmYgPC0gcmVhZC50YWJsZShwYXN0ZTAoYmFzZWZvbGRlciwgZXhwSUQsICIvaW5wdXQvYWxsR2VuZXNEZWNyRXF1YWxzU3lucldpdGhTY2FsaW5nXyIsIGRjLnIuZGYkcGFyYUNvbWJvW2krMV0sICJfUy5jZXIubVJOQS5pbmkuYWJuZGMuc3luLmRlYyIpKQogICAgdG90LmluLmRyWywgaV0gPC0gKGluZlssIDRdKmluZlssIDJdKQp9CgptbWRyQWxsZ2VuZUFsbGRjciA8LSByZWFkX2ZlYXRoZXIocGFzdGUwKGJhc2Vmb2xkZXIsIGV4cElELCAiL2FuYWx5c2VzL2ZlYXRoZXJGaWxlcy9tbWRyQWxsZ2VuZUFsbGRjci5mZWF0aGVyIikpWywgMjpucm93KGRjLnIuZGYpXQptbWNBbGxnZW5lQWxsZGNyPC0gcmVhZF9mZWF0aGVyKHBhc3RlMChiYXNlZm9sZGVyLCBleHBJRCwgIi9hbmFseXNlcy9mZWF0aGVyRmlsZXMvbW1jQWxsZ2VuZUFsbGRjci5mZWF0aGVyIikpWywgMjpucm93KGRjLnIuZGYpXQp0b3Qub3V0LmRyIDwtIG1tZHJBbGxnZW5lQWxsZGNyKm1tY0FsbGdlbmVBbGxkY3IKCm91dGRmIDwtIHRvdC5vdXQuZHIvdG90LmluLmRyCmNvbG5hbWVzKG91dGRmKSA8LSBkYy5yLmRmJHBhcmFDb21ib1syOm5yb3coZGMuci5kZildCgpvdXRkZlstMTI3OCwgXSAlPiUgICAgICAgIyBnZW5lIHdpdGggdGhlIEhMLW1pbj00OTAgbWluLCB0aGUgZGF0YSBwb2ludCBza2V3cyB0aGUgc2NhbGVzCiAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gInBhcmFDb21ibyIsIHZhbHVlc190byA9ICJvdXRJbkRyUmF0aW8iLCBjb2xzID0gMToobnJvdyhkYy5yLmRmKS0xKSkgJT4lCiAgbGVmdF9qb2luKC4sIGRjLnIuZGYsIGJ5ID0gInBhcmFDb21ibyIpICU+JQogIGZpbHRlcihvdXRJbkRyUmF0aW8gIT0gMCkgJT4lCiAgbXV0YXRlKGRjX2ZjdD1mYWN0b3IoZGMsIGxldmVscz1jKCIxIiwgIjAuOCIsICIwLjYiLCAiMC40IiwgIjAuMiIsICIwIikpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGNfZmN0LCB5PW91dEluRHJSYXRpbywgZmlsbD1yKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAwLjEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PW1lZGlhbihhcy5udW1lcmljKHVubGlzdChvdXRkZiAlPiVzZWxlY3QoZGNfMV9yXzApKSlbLTEyNzhdLCBuYS5ybSA9IFRSVUUpKSwgCiAgICAgICAgICAgICBjb2xvcj0icmVkIiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHg9IkNNRCBsZXZlbCIsCiAgICAgICB5PSJSYXRpbyBiZXR3ZWVuIHRvdGFsIG91dHB1dC9pbnB1dCBkZWNheSByYXRlcyIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCIxIj0iMTAwJSIsICIwLjgiPSI4MCUiLCAiMC42Ij0iNjAlIiwgIjAuNCI9IjQwJSIsICIwLjIiPSIyMCUiLCAiMCI9IjAiKSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJSaWJvc29tZVxucHJvdCBpbmRleCIpICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICkKCgojIyMjIyMjIyMjIyMjIwpvdXRkZiA8LSB0aWJibGUobWF0cml4KE5BLCBuY29sPW5yb3coZGMuci5kZiktMSwgbnJvdz00ODM5KSkgI2NvbnRhaW5zIGFsbCB0aGUgdG90YWwgaW5wdXQgZGVjYXkgcmF0ZXMKCmZvciAoaSBpbiAxOihucm93KGRjLnIuZGYpLTEpKSAgIyB0aGVzZSAxNiBjb2x1bW5zIGFyZSBhbGwgdGhlIHNhbWUsIGFsbCBlcXVhbCB0byBzaW1JbnB1dEZlYXR1cmVzJG1STkFhYnVuZGFuY2Uqc2ltSW5wdXRGZWF0dXJlcyRtUk5BRGVjUmF0ZU5leW1vdGluX3NlYwp7CiAgICBpbmYgPC0gcmVhZC50YWJsZShwYXN0ZTAoYmFzZWZvbGRlciwgZXhwSUQsICIvaW5wdXQvYWxsR2VuZXNEZWNyRXF1YWxzU3lucldpdGhTY2FsaW5nXyIsIGRjLnIuZGYkcGFyYUNvbWJvW2krMV0sICJfUy5jZXIubVJOQS5pbmkuYWJuZGMuc3luLmRlYyIpKQogICAgb3V0ZGZbLCBpXSA8LSAoaW5mWywgNF0qaW5mWywgMl0pCn0KCgpvdXRkZiA8LSB0b3Rkci9vdXRkZgpjb2xuYW1lcyhvdXRkZikgPC0gZGMuci5kZiRwYXJhQ29tYm9bMjpucm93KGRjLnIuZGYpXQoKCm91dGRmICU+JQogIG11dGF0ZShtUk5BYWJ1bmRhbmNlPXNpbUlucHV0RmVhdHVyZXMkbVJOQWFidW5kYW5jZSwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWM9c2ltSW5wdXRGZWF0dXJlcyRtUk5BRGVjUmF0ZU5leW1vdGluX3NlYywgT1JGPXNpbUlucHV0RmVhdHVyZXMkT1JGKSAlPiUKICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAicGFyYUNvbWJvIiwgdmFsdWVzX3RvID0gInJhdGlvVmFsIiwgY29scyA9ICFjKG1STkFhYnVuZGFuY2UsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjLCBPUkYpKSAlPiUKICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18wX3JfMSIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIikgJT4lCiAgZ2dwbG90KGFlcyh4PW1STkFhYnVuZGFuY2UsIHk9cmF0aW9WYWwpKSArCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZV9idygpICsKICBzY2FsZV94X2xvZzEwKCkKICAKYGBgCgoKCgoKCgoKCkZpZy4gUwpgYGB7cn0KbCAlPiUKICBmaWx0ZXIocGFyYUNvbWJvID09ICJkY18xX3JfMCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUNSMDI0Qy1CIiwgbVJOQWFidW5kYW5jZSAhPSAxKSAlPiUKICBtdXRhdGUocmVsYXRpdmVGYW5vID0gUk1WUFMvUk1QU1IpICU+JQogIGdncGxvdChhZXMoeD1STVBTUiwgeT1yZWxhdGl2ZUZhbm8pKSArCiAgZ2VvbV9wb2ludChzaXplPTAuMSkgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgc2NhbGVfeV9sb2cxMCgpICsKICAgICAgbGFicyh4PSAiUmVhbHRpdmUgbWVhbiBwcm90ZWluIHN5bnRoZXNpcyByYXRlIiwKICAgICAgICB5ID0gIlJlbGF0aXZlIGZhbm8gZmFjdG9yIGluIHByb3RlaW4gc3ludGhlc2lzIHJhdGUiLAogICAgICAgIHRpdGxlID0gIiIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsPXBhc3RlKC4uci5sYWJlbC4uLCBzZXAgPSAifmAsIGB+IikpLCBsYWJlbC54Lm5wYyA9IDAuMSwgbGFiZWwueS5ucGMgPSAwLjMsIHNpemU9MykgKyAKICAgIHRoZW1lX2J3KCkgCgoKCmBgYAoKCmBgYHtyfQphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZQ1IwMjRDLUIiLCBtUk5BYWJ1bmRhbmNlICE9IDEpICU+JQogICAgZ2dwbG90KGFlcyh4PU1SRCwgeT1STVZURSkpICsKICAgIGdlb21fcG9pbnQoc2l6ZT0wLjEpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh4PSAiTWVhbiByaWJvc29tZSBkZW5zaXR5IiwKICAgICAgICB5ID0gIlJlbGF0aXZlIG1lYW4gb2YgdmFyaWFuY2UgaW4gdHJhbnNsYXRpb24gZWZmaWNpZW5jeSIsCiAgICAgICAgdGl0bGUgPSAiIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsgCiAgICBzdGF0X2NvcihhZXMobGFiZWw9cGFzdGUoLi5yLmxhYmVsLi4sIHNlcCA9ICJ+YCwgYH4iKSksIGxhYmVsLngubnBjID0gMC4xLCBsYWJlbC55Lm5wYyA9IDAuMywgc2l6ZT0zKSArIAogICAgdGhlbWVfYncoKSAKCgphbGxTaW1JbnB1dE91dHB1dCAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZQ1IwMjRDLUIiLCBtUk5BYWJ1bmRhbmNlICE9IDEpICU+JQogICAgZ2dwbG90KGFlcyh4PU1NRFAsIHk9bVJOQURlY1JhdGVOZXltb3Rpbl9zZWMpKSArCiAgICBnZW9tX3BvaW50KHNpemU9MC4xKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnMoeD0gIk1lYW4gcmlib3NvbWUgZGVuc2l0eSIsCiAgICAgICAgeSA9ICJSZWxhdGl2ZSBtZWFuIG9mIHZhcmlhbmNlIGluIHRyYW5zbGF0aW9uIGVmZmljaWVuY3kiLAogICAgICAgIHRpdGxlID0gIiIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSArIAogICAgc3RhdF9jb3IoYWVzKGxhYmVsPXBhc3RlKC4uci5sYWJlbC4uLCAgc2VwID0gIn5gLCBgfiIpKSwgbGFiZWwueC5ucGMgPSAwLjEsIGxhYmVsLnkubnBjID0gMC4zLCBzaXplPTMpICsgCiAgICB0aGVtZV9idygpIAoKYGBgCgoKCkZpZ3VyZSBTLgpgYGB7cn0KCiMgY2FsY3VsYXRpbmcgdGhlIG1lYW4gbnVtYmVyIG9mIGZyZWUgcmlib3MgKGF2ZXJhZ2VkIG92ZXIgc2ltdVRpbWUgYW5kIHRlY2hSZXBzKSBmb3IgYWxsIGRjLnIucGFyYUNvbWJvcwojIFJNRlIgPSByZWxhdGl2ZSBtZWFuIGZyZWUgcmlibwptZnIgPC0gYygpIApmb3IoaSBpbiAxOm5yb3coZGMuci5kZikpICMgbG9vcCB0aHJvdWdoIHRoZSBkYy9yIHBhcmFtZXRlciBzcGFjZSB0byBjYWxjdWxhdGUgdGhlIG1lYW4gZnJlZSByaWJvCnsKICAgICMgZnJlZV9yaWJvIGF2ZXJhZ2VkIGJ5IHNpbXVUaW1lIGFuZCB0ZWNoUmVwcwogICAgbWZyIDwtIGMobWZyLCBtZWFuKGg1cmVhZChzaW1PdXRwdXRINSwgcGFzdGUoImZyZWVfcmlib190Uk5BX3Blck1pbiIsIGRjLnIuZGYkcGFyYUNvbWJvW2ldLCAicmlibyIsIHNlcD0iLyIpKSwgbmEucm0gPSBUUlVFKSkKICAgICMgc2V0IG5hLnJtPVQgYmVjYXVzZSBpbiByZXAgNjYgYWdhaW4gdGhlcmUncyBhbiBOQSBhdCB0aGUgbGFzdCBtaW51dGUsIHdoaWNoIHdvbid0IGFmZmVjdCB0aGUgb3ZlcmFsbCBtZWFuCn0KCnJtZnIgPC0gbWZyL21mclsxXQpybWZyX2RmIDwtIGRhdGEuZnJhbWUoUk1GUiA9IHJtZnIsCiAgICAgICAgICAgICAgICAgICAgICBNRlIgPSBtZnIsCiAgICAgICAgICAgICAgICAgICAgICBwYXJhID0gZGMuci5kZiRwYXJhKQoKIyBybWZyX2RmIGNhbiBiZSBmb3VuZCBpbiBleHAwX3ByZXBQbG90cy5SbWQKcm1mcl9kZiAlPiUKICBsZWZ0X2pvaW4oLiwgZGMuci5kZiwgYnkgPSJwYXJhIikgJT4lCiAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IikgJT4lCiAgc2VsZWN0KFJNRlIsIGRjLCByKSAlPiUKICBzcHJlYWQoZGMsIFJNRlIpICU+JQogIHNlbGVjdCgtcikgJT4lCiAgY29sTWVhbnMoKSAlPiUKICB0aWJibGUoKSAlPiUgCiAgbXV0YXRlKGRjPWFzLmNoYXJhY3RlcihzZXEoMCwgMSwgYnk9MC4yKSkpICU+JQogIGBjb2xuYW1lczwtYChjKCJSTUZSbWVhbkJ5Q29UcmFucyIsICJkYyIpKSAlPiUKICAgIG11dGF0ZShjb3RyYW5zID0gcGFzdGUwKGFzLm51bWVyaWMoZGMpKjEwMCwgIiUiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9Y290cmFucywgeT1STUZSbWVhbkJ5Q29UcmFucykpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICB0aGVtZV9idygpICsKICAgIGxhYnMgKCB0aXRsZSA9ICIiLAogICAgICAgICAgICAgICAgeCA9IkNvLXRyYW5zbGF0aW9uYWwgZGVjYXkgcHJvcG9ydGlvbiIsCiAgICAgICAgICAgICAgICB5ID0gIk1lYW4gZnJlZSByaWJvc29tZXMgKHJlbGF0aXZlIHRvIG1STkEgY29uc3RhbnQpIikgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCIxMDAlIiwgIjgwJSIsICI2MCUiLCAiNDAlIiwgIjIwJSIsICIwJSIpKQogIApgYGAKCmBgYHtyfQoKbWFrZV9oZWF0bWFwIDwtIGZ1bmN0aW9uKG9yZGVyVmFyLCBvdXRwdXRWYXIsIGxlZ2VuZE5hbWUsIHRpdGxlWSkKewogICAgY29sb3J2ZWMgPC0gcXVhbnRpbGUoYWxsU2ltSW5wdXRPdXRwdXRbW291dHB1dFZhcl1dKQogIAogICAgdG1wIDwtIChhbGxTaW1JbnB1dE91dHB1dCU+JWZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIikpWywgYygiT1JGIiwgb3JkZXJWYXIpXQogICAgdG1wIDwtIHRtcFtvcmRlcih0bXBbLCAyXSwgZGVjcmVhc2luZyA9IFQpLCBdCiAgICB0bXAkbmV3aWRfZGMxcjAgPC0gMTo0ODM5CiAgICAKICAgIGFsbFNpbUlucHV0T3V0cHV0ICU+JSAKICAgICAgICBmaWx0ZXIocGFyYUNvbWJvICE9ICJtUk5BY29uc3RhbnQiKSAlPiUgCiAgICAgICAgbGVmdF9qb2luKC4sIHRtcFssIGMoIk9SRiIsICJuZXdpZF9kYzFyMCIpXSwgYnkgPSAiT1JGIikgJT4lCiAgICAgICAgbXV0YXRlKGRjX2ZjdD1mYWN0b3IoZGMsIGxldmVscz1jKCIxIiwgIjAuOCIsICIwLjYiLCAiMC40IiwgIjAuMiIsICIwIikpKSAlPiUKICAgICAgICBnZ3Bsb3QoYWVzX3N0cmluZyh4ID0gInIiLCAKICAgICAgICAgICAgICAgICAgIHkgPSAiZmFjdG9yKG5ld2lkX2RjMXIwKSIsCiAgICAgICAgICAgICAgICAgICBmaWxsID0gb3V0cHV0VmFyKSkgKwogICAgICAgIGdlb21fcmFzdGVyKCkgKwogICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSBjKCIjMzc3ZWI4IiwgIndoaXRlIiwgIiNlNDFhMWMiKSwgICAjIGJsdWUgd2hpdGUgcmVkCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IHNjYWxlczo6cmVzY2FsZShjb2xvcnZlYyksIG5hbWU9bGVnZW5kTmFtZSkgKwogICAgICAgIGZhY2V0X3dyYXAofmRjX2ZjdCwgbnJvdz0xLCBsYWJlbGxlcj1sYWJlbGxlcihkY19mY3Q9YygiMSI9IkNvLXRyYW5zIDEwMCUiLCAiMC44Ij0iODAlIiwgIjAuNiI9IjYwJSIsICIwLjQiPSI0MCUiLCAiMC4yIj0iMjAlIiwgIjAiPSIwIikpKSArIAogICAgICAgIGxhYnMgKCB4ID0gIlJpYm9zb21lIHByb3RlY3Rpb24gaW5kZXggciIsCiAgICAgICAgICAgICAgIHkgPSB0aXRsZVksCiAgICAgICAgICAgICAgIHRpdGxlID0gIiIpICsKICAgICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgICMgcmVtb3ZlIHRoZSBncmlkIGxpbmVzIGluIGZhY2V0X2dyaWQKICAgICAgICAgICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoMCwgImxpbmVzIikpICsgICAjIHJlc2V0IHRoZSBzcGFjaW5nIGJldHdlZW4gZmFjZXRzCiAgICAgICAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMSwgYmFyaGVpZ2h0ID0gMTApKSArCiAgICAgICAgIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLCAwKSkgIyByZW1vdmUgdGhlIGV4dHJhIHNwYWNlIGJleW9uZCB4bGltCgp9CgoKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTh9CiMgMXN0IHZhcj0gdGhlIHZhcmlhYmxlIGNvbHVtbiB0aGUgc29ydGluZyBpcyBiYXNlZCBvbgojIDJuZCB2YXI9IHRoZSB2YXJpYWJsZSBjb2x1bW4gcHJlc2VudGVkIGluIHRoZSBoZWF0bWFwCiMgM3JkIHZhcj0gdGhlIGxlZ2VuZCB0ZXh0CiMgNHRoIHZhcj0geS1heGlzIHRpdGxlCgptYWtlX2hlYXRtYXAoIlJNVEUiLCAiUk1URSIsICJSZWxhdGl2ZVxubWVhbiB0cmFuc2xhdGlvblxuZWZmaWNpZW5jeSIsICJHZW5lcyByYW5rZWQgYnkgdGhlIGZpcnN0IGNvbHVtbiIpCm1ha2VfaGVhdG1hcCgiUk1WVEUiLCAiUk1WVEUiLCAiUmVsYXRpdmUgbWVhblxub2YgdGhlIHZhcmlhbmNlXG5pbiB0cmFuc2xhdGlvblxuZWZmaWNpZW5jeSIsICJHZW5lcyByYW5rZWQgYnkgdGhlIGZpcnN0IGNvbHVtbiIpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIGFkZCBhIHBsb3QgZm9yIG1STkFzIG1hcmtlZCBmb3IgZGVjYXkKY29sb3J2ZWMgPC0gcXVhbnRpbGUoKGFsbFNpbUlucHV0T3V0cHV0JT4lIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIikpJE1NRFApCgp0bXAgPC0gKGFsbFNpbUlucHV0T3V0cHV0JT4lZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMV9yXzAiKSlbLCBjKCJPUkYiLCAiUk1URSIpXQp0bXAgPC0gdG1wW29yZGVyKHRtcFssIDJdLCBkZWNyZWFzaW5nID0gVCksIF0KdG1wJG5ld2lkX2RjMXIwIDwtIDE6NDgzOQoKYWxsU2ltSW5wdXRPdXRwdXQgJT4lIAogICAgbXV0YXRlKGRjX2ZjdD1mYWN0b3IoZGMsIGxldmVscz1jKCIxIiwgIjAuOCIsICIwLjYiLCAiMC40IiwgIjAuMiIsICIwIikpKSAlPiUKICAgIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIiwgZGMgIT0gMCkgJT4lIAogICAgbGVmdF9qb2luKC4sIHRtcFssIGMoIk9SRiIsICJuZXdpZF9kYzFyMCIpXSwgYnkgPSAiT1JGIikgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSByLCAKICAgICAgICAgICAgICAgeSA9IGZhY3RvcihuZXdpZF9kYzFyMCksCiAgICAgICAgICAgICAgICN5ID0gYXMuY2hhcmFjdGVyKG5ld2lkX2dlbmVMZW5ndGhfY29kb24pLCAgICMgZ2VuZXMgYXJlIHNvcnRlZCBieSBnZW5lTGVuZ3RoX2NvZG9uIHdpdGhpbiBlYWNoIGdyb3VwCiAgICAgICAgICAgICAgIGZpbGwgPSBNTURQKSkgKwogICAgZ2VvbV9yYXN0ZXIoKSArCiAgICB0aGVtZV9idygpICsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSBjKCIjMzc3ZWI4IiwgIndoaXRlIiwgIiNlNDFhMWMiKSwgICAjIGJsdWUgd2hpdGUgcmVkCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gc2NhbGVzOjpyZXNjYWxlKGNvbG9ydmVjKSwgbmFtZT0ibVJOQXMgbWFya2VkXG5mb3IgZGVjYXkgcmF0aW8iKSArCiAgICBmYWNldF93cmFwKH5kY19mY3QsIG5yb3c9MSwgbGFiZWxsZXI9bGFiZWxsZXIoZGNfZmN0PWMoIjEiPSJDby10cmFucyAxMDAlIiwgIjAuOCI9IjgwJSIsICIwLjYiPSI2MCUiLCAiMC40Ij0iNDAlIiwgIjAuMiI9IjIwJSIsICIwIj0iMCUiKSkpICsKICAgIGxhYnMgKCB4ID0gIlJpYm9zb21lIHByb3RlY3Rpb24gaW5kZXggdyIsCiAgICAgICAgICAgeSA9ICJHZW5lcyByYW5rZWQgYnkgdGhlIGZpcnN0IGNvbHVtbiBpbiB0cmFuc2xhdGlvbiBlZmZpY2llbmN5IHBsb3QiLAogICAgICAgICAgIHRpdGxlID0gIiIpICsKICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS41KSksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgICMgcmVtb3ZlIHRoZSBncmlkIGxpbmVzIGluIGZhY2V0X2dyaWQKICAgICAgICAgIHBhbmVsLnNwYWNpbmc9dW5pdCgwLCAibGluZXMiKSkgKyAgICMgcmVzZXQgdGhlIHNwYWNpbmcgYmV0d2VlbiBmYWNldHMKICAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDEsIGJhcmhlaWdodCA9IDEwKSkgKwogICAgIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLCAwKSkgIyByZW1vdmUgdGhlIGV4dHJhIHNwYWNlIGJleW9uZCB4bGltCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBhZGQgYW5vdGhlciBwbG90IGZvciBtUk5BcyBtYXJrZWQgZm9yIGRlY2F5CmNvbG9ydmVjIDwtIHF1YW50aWxlKChhbGxTaW1JbnB1dE91dHB1dCU+JSBmaWx0ZXIocGFyYUNvbWJvICE9ICJtUk5BY29uc3RhbnQiLCBtUk5BRGVjUmF0ZU5leW1vdGluX3NlYyAhPSAwLCBPUkYgIT0gIllFUjA1M0MtQSIpKSRNTURQKQoKdG1wIDwtIChhbGxTaW1JbnB1dE91dHB1dCU+JWZpbHRlcihwYXJhQ29tYm8gPT0gImRjXzFfcl8wIikpWywgYygiT1JGIiwgIlJNVlRFIildCnRtcCA8LSB0bXBbb3JkZXIodG1wWywgMl0sIGRlY3JlYXNpbmcgPSBUKSwgXQp0bXAkbmV3aWRfZGMxcjAgPC0gMTo0ODM5CgphbGxTaW1JbnB1dE91dHB1dCAlPiUgCiAgICBtdXRhdGUoZGNfZmN0PWZhY3RvcihkYywgbGV2ZWxzPWMoIjEiLCAiMC44IiwgIjAuNiIsICIwLjQiLCAiMC4yIiwgIjAiKSkpICU+JQogICAgZmlsdGVyKHBhcmFDb21ibyAhPSAibVJOQWNvbnN0YW50IiwgbVJOQURlY1JhdGVOZXltb3Rpbl9zZWMgIT0gMCwgT1JGICE9ICJZRVIwNTNDLUEiLCBkYyAhPSAwKSAlPiUgCiAgICBsZWZ0X2pvaW4oLiwgdG1wWywgYygiT1JGIiwgIm5ld2lkX2RjMXIwIildLCBieSA9ICJPUkYiKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IHIsIAogICAgICAgICAgICAgICB5ID0gZmFjdG9yKG5ld2lkX2RjMXIwKSwKICAgICAgICAgICAgICAgZmlsbCA9IE1NRFApKSArCiAgICBnZW9tX3Jhc3RlcigpICsKICAgIHRoZW1lX2J3KCkgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IGMoIiMzNzdlYjgiLCAid2hpdGUiLCAiI2U0MWExYyIpLCAgICMgYmx1ZSB3aGl0ZSByZWQKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBzY2FsZXM6OnJlc2NhbGUoY29sb3J2ZWMpLCBuYW1lPSJtUk5BcyBtYXJrZWRcbmZvciBkZWNheSByYXRpbyIpICsKICAgIGZhY2V0X3dyYXAofmRjX2ZjdCwgbnJvdz0xLCBsYWJlbGxlcj1sYWJlbGxlcihkY19mY3Q9YygiMSI9IkNvLXRyYW5zIDEwMCUiLCAiMC44Ij0iODAlIiwgIjAuNiI9IjYwJSIsICIwLjQiPSI0MCUiLCAiMC4yIj0iMjAlIiwgIjAiPSIwJSIpKSkgKwogICAgbGFicyAoIHggPSAiUmlib3NvbWUgcHJvdGVjdGlvbiBpbmRleCB3IiwKICAgICAgICAgICB5ID0gIkdlbmVzIHJhbmtlZCBieSB0aGUgZmlyc3QgY29sdW1uIGluIHRyYW5zbGF0aW9uIGVmZmljaWVuY3kgcGxvdCIsCiAgICAgICAgICAgdGl0bGUgPSAiIikgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjUpKSwKICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLCAgIyByZW1vdmUgdGhlIGdyaWQgbGluZXMgaW4gZmFjZXRfZ3JpZAogICAgICAgICAgcGFuZWwuc3BhY2luZz11bml0KDAsICJsaW5lcyIpKSArICAgIyByZXNldCB0aGUgc3BhY2luZyBiZXR3ZWVuIGZhY2V0cwogICAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMSwgYmFyaGVpZ2h0ID0gMTApKSArCiAgICAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSAjIHJlbW92ZSB0aGUgZXh0cmEgc3BhY2UgYmV5b25kIHhsaW0KCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9OH0KIyAxc3QgdmFyPSB0aGUgdmFyaWFibGUgY29sdW1uIHRoZSBzb3J0aW5nIGlzIGJhc2VkIG9uCiMgMm5kIHZhcj0gdGhlIHZhcmlhYmxlIGNvbHVtbiBwcmVzZW50ZWQgaW4gdGhlIGhlYXRtYXAKIyAzcmQgdmFyPSB0aGUgbGVnZW5kIHRleHQKIyA0dGggdmFyPSB5LWF4aXMgdGl0bGUKCm1ha2VfaGVhdG1hcCgiUk1QU1IiLCAiUk1QU1IiLCAiUmVsYXRpdmVcbm1lYW4gcHJvdGVpblxuc3luIHJhdGUiLCAiR2VuZXMgcmFua2VkIGJ5IHRoZSBmaXJzdCBjb2x1bW4iKQptYWtlX2hlYXRtYXAoIlJNVlBTIiwgIlJNVlBTIiwgIlJlbGF0aXZlXG5tZWFuIG9mIHZhcmlhbmNlIGluXG5wcm90ZWluIHN5biByYXRlIiwgIkdlbmVzIHJhbmtlZCBieSB0aGUgZmlyc3QgY29sdW1uIikKCm1ha2VfaGVhdG1hcF90bXAgPC0gZnVuY3Rpb24ob3JkZXJWYXIsIG91dHB1dFZhciwgbGVnZW5kTmFtZSwgdGl0bGVZKQp7CiAgICBjb2xvcnZlYyA8LSBxdWFudGlsZShhbGxTaW1JbnB1dE91dHB1dFtbb3V0cHV0VmFyXV0pCiAgCiAgICB0bXAgPC0gKGFsbFNpbUlucHV0T3V0cHV0JT4lZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMV9yXzAiKSlbLCBjKCJPUkYiLCBvcmRlclZhcildCiAgICB0bXAgPC0gdG1wW29yZGVyKHRtcFssIDJdLCBkZWNyZWFzaW5nID0gVCksIF0KICAgIHRtcCRuZXdpZF9kYzFyMCA8LSAxOjQ4MzkKICAgIAogICAgYWxsU2ltSW5wdXRPdXRwdXQgJT4lIAogICAgICAgIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIsIFJNVlRCUiAhPSBJbmYpICU+JSAKICAgICAgICBsZWZ0X2pvaW4oLix0bXBbLCBjKCJPUkYiLCAibmV3aWRfZGMxcjAiKV0sIGJ5ID0gIk9SRiIpICU+JQogICAgICAgIG11dGF0ZShkY19mY3Q9ZmFjdG9yKGRjLCBsZXZlbHM9YygiMSIsICIwLjgiLCAiMC42IiwgIjAuNCIsICIwLjIiLCAiMCIpKSkgJT4lCiAgICAgICAgZ2dwbG90KGFlc19zdHJpbmcoeCA9ICJyIiwgCiAgICAgICAgICAgICAgICAgICB5ID0gImZhY3RvcihuZXdpZF9kYzFyMCkiLAogICAgICAgICAgICAgICAgICAgZmlsbCA9IG91dHB1dFZhcikpICsKICAgICAgICBnZW9tX3Jhc3RlcigpICsKICAgICAgICB0aGVtZV9idygpICsKICAgICAgICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzID0gYygiIzM3N2ViOCIsICJ3aGl0ZSIsICIjZTQxYTFjIiksICAgIyBibHVlIHdoaXRlIHJlZAogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBzY2FsZXM6OnJlc2NhbGUoY29sb3J2ZWMpLCBuYW1lPWxlZ2VuZE5hbWUpICsKICAgICAgICBmYWNldF93cmFwKH5kY19mY3QsIG5yb3c9MSwgbGFiZWxsZXI9bGFiZWxsZXIoZGNfZmN0PWMoIjEiPSJDby10cmFucyAxMDAlIiwgIjAuOCI9IjgwJSIsICIwLjYiPSI2MCUiLCAiMC40Ij0iNDAlIiwgIjAuMiI9IjIwJSIsICIwIj0iMCIpKSkgKyAKICAgICAgICBsYWJzICggeCA9ICJSaWJvc29tZSBwcm90ZWN0aW9uIGluZGV4IHIiLAogICAgICAgICAgICAgICB5ID0gdGl0bGVZLAogICAgICAgICAgICAgICB0aXRsZSA9ICIiKSArCiAgICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksICAjIHJlbW92ZSB0aGUgZ3JpZCBsaW5lcyBpbiBmYWNldF9ncmlkCiAgICAgICAgICAgICAgcGFuZWwuc3BhY2luZz11bml0KDAsICJsaW5lcyIpKSArICAgIyByZXNldCB0aGUgc3BhY2luZyBiZXR3ZWVuIGZhY2V0cwogICAgICAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDEsIGJhcmhlaWdodCA9IDEwKSkgKwogICAgICAgICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCkpICMgcmVtb3ZlIHRoZSBleHRyYSBzcGFjZSBiZXlvbmQgeGxpbQoKfQptYWtlX2hlYXRtYXBfdG1wKCJSTVRFIiwgIlJNVlRCUiIsICJSZWxhdGl2ZVxudmFyaWFuY2UgaW4gdG90YWxcbmJvdW5kIHJpYm9zb21lcyIsICJHZW5lcyByYW5rZWQgYnkgdGhlIGZpcnN0IGNvbHVtbiBpbiByZWxhdGl2ZSBURSIpCgoKbWFrZV9oZWF0bWFwKCJNTUwiLCAiTU1MIiwgIk1lYW4gb2YgbVJOQVxubGlmZS10aW1lcyIsICJHZW5lcyByYW5rZWQgYnkgdGhlIGZpcnN0IGNvbHVtbiIpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKY29sb3J2ZWMgPC0gcXVhbnRpbGUoKGFsbFNpbUlucHV0T3V0cHV0JT4lIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIikpJFJNUkQpCgp0bXAgPC0gKGFsbFNpbUlucHV0T3V0cHV0JT4lZmlsdGVyKHBhcmFDb21ibyA9PSAiZGNfMV9yXzAiKSlbLCBjKCJPUkYiLCAiUk1URSIpXQp0bXAgPC0gdG1wW29yZGVyKHRtcFssIDJdLCBkZWNyZWFzaW5nID0gVCksIF0KdG1wJG5ld2lkX2RjMXIwIDwtIDE6NDgzOQoKCmFsbFNpbUlucHV0T3V0cHV0ICU+JSAKICAgIGZpbHRlcihwYXJhQ29tYm8gIT0gIm1STkFjb25zdGFudCIsIG1STkFEZWNSYXRlTmV5bW90aW5fc2VjICE9IDAsIE9SRiAhPSAiWUVSMDUzQy1BIikgJT4lIAogICAgbGVmdF9qb2luKC4sIHRtcFssIGMoIk9SRiIsICJuZXdpZF9kYzFyMCIpXSwgYnkgPSAiT1JGIikgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSByLCAKICAgICAgICAgICAgICAgeSA9IGZhY3RvcihuZXdpZF9kYzFyMCksCiAgICAgICAgICAgICAgIGZpbGwgPSBSTVJEKSkgKwogICAgZ2VvbV9yYXN0ZXIoKSArCiAgICB0aGVtZV9idygpICsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSBjKCIjMzc3ZWI4IiwgIndoaXRlIiwgIiNlNDFhMWMiKSwgICAjIGJsdWUgd2hpdGUgcmVkCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gc2NhbGVzOjpyZXNjYWxlKGNvbG9ydmVjKSwgbmFtZT0iUmVsYXRpdmUgbWVhblxucmlibyBkZW5zaXR5IikgKwogICAgZmFjZXRfd3JhcCh+ZGMsIG5yb3c9MSwgbGFiZWxsZXI9bGFiZWxsZXIoZGM9YygiMSI9IkNvLXRyYW5zIDEwMCUiLCAiMC44Ij0iMC44IiwgIjAuNiI9IjAuNiIsICIwLjQiPSIwLjQiLCAiMC4yIj0iMC4yIiwgIjAiPSIwIikpKSArCiAgICBsYWJzICggeCA9ICJSaWJvc29tZSBwcm90ZWN0aW9uIGluZGV4IiwKICAgICAgICAgICB5ID0gIkdlbmVzIHJhbmtlZCBieSB0aGUgZmlyc3QgY29sdW1uIGZvciB0cmFuc2xhdGlvbiBlZmZpY2llbmN5IiwKICAgICAgICAgICB0aXRsZSA9ICIiKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuNSkpLAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksICAjIHJlbW92ZSB0aGUgZ3JpZCBsaW5lcyBpbiBmYWNldF9ncmlkCiAgICAgICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoMCwgImxpbmVzIikpICsgICAjIHJlc2V0IHRoZSBzcGFjaW5nIGJldHdlZW4gZmFjZXRzCiAgICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAxLCBiYXJoZWlnaHQgPSAxMCkpICsKICAgICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCkpICMgcmVtb3ZlIHRoZSBleHRyYSBzcGFjZSBiZXlvbmQgeGxpbQpgYGAK